PageRenderTime 136ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 2ms

/SpecSharp/System.Compiler/Nodes.cs

#
C# | 12405 lines | 11377 code | 111 blank | 917 comment | 3958 complexity | b111ae665abe1b7131c5e7543d4a30e7 MD5 | raw file
  1. //-----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) Microsoft Corporation. All Rights Reserved.
  4. //
  5. //-----------------------------------------------------------------------------
  6. using System;
  7. using System.Collections;
  8. using System.Collections.Generic;
  9. using System.Globalization;
  10. using System.Collections.Specialized;
  11. #if FxCop
  12. using AssemblyReferenceList = Microsoft.Cci.AssemblyReferenceCollection;
  13. using AttributeList = Microsoft.Cci.AttributeNodeCollection;
  14. using BlockList = Microsoft.Cci.BlockCollection;
  15. using ExpressionList = Microsoft.Cci.ExpressionCollection;
  16. using InstructionList = Microsoft.Cci.InstructionCollection;
  17. using Int32List = System.Collections.Generic.List<int>;
  18. using InterfaceList = Microsoft.Cci.InterfaceCollection;
  19. using MemberList = Microsoft.Cci.MemberCollection;
  20. using MethodList = Microsoft.Cci.MethodCollection;
  21. using ModuleReferenceList = Microsoft.Cci.ModuleReferenceCollection;
  22. using NamespaceList = Microsoft.Cci.NamespaceCollection;
  23. using ParameterList = Microsoft.Cci.ParameterCollection;
  24. using ResourceList = Microsoft.Cci.ResourceCollection;
  25. using SecurityAttributeList = Microsoft.Cci.SecurityAttributeCollection;
  26. using StatementList = Microsoft.Cci.StatementCollection;
  27. using TypeNodeList = Microsoft.Cci.TypeNodeCollection;
  28. using Win32ResourceList = Microsoft.Cci.Win32ResourceCollection;
  29. using Module = Microsoft.Cci.ModuleNode;
  30. using Class = Microsoft.Cci.ClassNode;
  31. using Interface = Microsoft.Cci.InterfaceNode;
  32. using Property = Microsoft.Cci.PropertyNode;
  33. using Event = Microsoft.Cci.EventNode;
  34. using Return = Microsoft.Cci.ReturnNode;
  35. using Throw = Microsoft.Cci.ThrowNode;
  36. #endif
  37. #if UseSingularityPDB
  38. using Microsoft.Singularity.PdbInfo;
  39. #endif
  40. #if CCINamespace
  41. using Cci = Microsoft.Cci;
  42. using Microsoft.Cci.Metadata;
  43. using Metadata = Microsoft.Cci.Metadata;
  44. #else
  45. using Cci = System.Compiler;
  46. using System.Compiler.Metadata;
  47. using Metadata = System.Compiler.Metadata;
  48. #endif
  49. using System.Diagnostics;
  50. using System.IO;
  51. using System.Text;
  52. #if !NoXml
  53. using System.Xml;
  54. #endif
  55. using BindingFlags = System.Reflection.BindingFlags;
  56. #if CCINamespace
  57. namespace Microsoft.Cci{
  58. #else
  59. namespace System.Compiler{
  60. #endif
  61. #if !FxCop
  62. /// <summary>
  63. /// This interface can be used to link an arbitrary source text provider into an IR tree via a DocumentText instance.
  64. /// </summary>
  65. public interface ISourceText{
  66. /// <summary>
  67. /// The number of characters in the source text.
  68. /// A "character" corresponds to a System.Char which is actually a Unicode UTF16 code point to be precise.
  69. /// </summary>
  70. int Length{get;}
  71. /// <summary>
  72. /// Retrieves a substring from this instance. The substring starts with the character at the specified index and has a specified length.
  73. /// </summary>
  74. string Substring(int startIndex, int length);
  75. /// <summary>
  76. /// Retrieves the character at the given position. The first character is at position zero.
  77. /// </summary>
  78. char this[int position]{get;}
  79. /// <summary>
  80. /// Indicates that the text has been fully scanned and futher references to the text are expected to be infrequent.
  81. /// The underlying object can now choose to clear cached information if it comes under resource pressure.
  82. /// </summary>
  83. void MakeCollectible();
  84. }
  85. public unsafe interface ISourceTextBuffer : ISourceText{
  86. /// <summary>
  87. /// Returns null unless the implementer is based on an ASCII buffer that stays alive as long at the implementer itself.
  88. /// An implementer that returns a non-null value is merely a wrapper to keep the buffer alive. No further methods will
  89. /// be called on the interface in this case.
  90. /// </summary>
  91. byte* Buffer{get;}
  92. }
  93. #endif
  94. #if !MinimalReader
  95. /// <summary>
  96. /// Use this after a source text has already been scanned and parsed. This allows the source text to get released
  97. /// if there is memory pressure, while still allowing portions of it to be retrieved on demand. This is useful when
  98. /// a large number of source files are read in, but only infrequent references are made to them.
  99. /// </summary>
  100. public sealed class CollectibleSourceText : ISourceText{
  101. private string/*!*/ filePath;
  102. private WeakReference/*!*/ fileContent;
  103. private int length;
  104. public CollectibleSourceText(string/*!*/ filePath, int length) {
  105. this.filePath = filePath;
  106. this.fileContent = new WeakReference(null);
  107. this.length = length;
  108. //^ base();
  109. }
  110. public CollectibleSourceText(string/*!*/ filePath, string fileContent) {
  111. this.filePath = filePath;
  112. this.fileContent = new WeakReference(fileContent);
  113. this.length = fileContent == null ? 0 : fileContent.Length;
  114. //^ base();
  115. }
  116. private string/*!*/ ReadFile() {
  117. string content = string.Empty;
  118. try {
  119. StreamReader sr = new StreamReader(filePath);
  120. content = sr.ReadToEnd();
  121. this.length = content.Length;
  122. sr.Close();
  123. }catch{}
  124. return content;
  125. }
  126. public string/*!*/ GetSourceText() {
  127. string source = (string)this.fileContent.Target;
  128. if (source != null) return source;
  129. source = this.ReadFile();
  130. this.fileContent.Target = source;
  131. return source;
  132. }
  133. int ISourceText.Length{get{return this.length;}}
  134. string ISourceText.Substring(int startIndex, int length){
  135. return this.GetSourceText().Substring(startIndex, length);
  136. }
  137. char ISourceText.this[int index]{
  138. get{
  139. return this.GetSourceText()[index];
  140. }
  141. }
  142. void ISourceText.MakeCollectible(){
  143. this.fileContent.Target = null;
  144. }
  145. }
  146. /// <summary>
  147. /// This class is used to wrap the string contents of a source file with an ISourceText interface. It is used while compiling
  148. /// a project the first time in order to obtain a symbol table. After that the StringSourceText instance is typically replaced with
  149. /// a CollectibleSourceText instance, so that the actual source text string can be collected. When a file is edited,
  150. /// and the editor does not provide its own ISourceText wrapper for its edit buffer, this class can be used to wrap a copy of the edit buffer.
  151. /// </summary>
  152. public sealed class StringSourceText : ISourceText{
  153. /// <summary>
  154. /// The wrapped string used to implement ISourceText. Use this value when unwrapping.
  155. /// </summary>
  156. public readonly string/*!*/ SourceText;
  157. /// <summary>
  158. /// True when the wrapped string is the contents of a file. Typically used to check if it safe to replace this
  159. /// StringSourceText instance with a CollectibleSourceText instance.
  160. /// </summary>
  161. public bool IsSameAsFileContents;
  162. public StringSourceText(string/*!*/ sourceText, bool isSameAsFileContents) {
  163. this.SourceText = sourceText;
  164. this.IsSameAsFileContents = isSameAsFileContents;
  165. //^ base();
  166. }
  167. int ISourceText.Length{get{return this.SourceText.Length;}}
  168. string ISourceText.Substring(int startIndex, int length){
  169. return this.SourceText.Substring(startIndex, length);
  170. }
  171. char ISourceText.this[int index]{
  172. get{
  173. return this.SourceText[index];
  174. }
  175. }
  176. void ISourceText.MakeCollectible(){
  177. }
  178. }
  179. #endif
  180. #if !FxCop
  181. /// <summary>
  182. /// This class provides a uniform interface to program sources provided in the form of Unicode strings,
  183. /// unsafe pointers to ascii buffers (as obtained from a memory mapped file, for instance) as well as
  184. /// arbitrary source text providers that implement the ISourceText interface.
  185. /// </summary>
  186. public sealed unsafe class DocumentText{
  187. /// <summary>
  188. /// If this is not null it is used to obtain 8-bit ASCII characters.
  189. /// </summary>
  190. public byte* AsciiStringPtr;
  191. /// <summary>
  192. /// If this is not null it represents a Unicode string encoded as UTF16.
  193. /// </summary>
  194. public string Source;
  195. /// <summary>
  196. /// If this is not null the object implement ISourceText provides some way to get at individual characters and substrings.
  197. /// </summary>
  198. public ISourceText TextProvider;
  199. /// <summary>
  200. /// The number of characters in the source document.
  201. /// A "character" corresponds to a System.Char which is actually a Unicode UTF16 code point to be precise.
  202. /// </summary>
  203. public int Length;
  204. public DocumentText(string source){
  205. if (source == null){Debug.Assert(false); return;}
  206. this.Source = source;
  207. this.Length = source.Length;
  208. }
  209. public DocumentText(ISourceText textProvider){
  210. if (textProvider == null){Debug.Assert(false); return;}
  211. this.TextProvider = textProvider;
  212. this.Length = textProvider.Length;
  213. }
  214. public unsafe DocumentText(ISourceTextBuffer textProvider){
  215. if (textProvider == null){Debug.Assert(false); return;}
  216. this.TextProvider = textProvider;
  217. this.AsciiStringPtr = textProvider.Buffer;
  218. this.Length = textProvider.Length;
  219. }
  220. /// <summary>
  221. /// Compare this.Substring(offset, length) for equality with str.
  222. /// Call this only if str.Length is known to be equal to length.
  223. /// </summary>
  224. public bool Equals(string str, int position, int length){ //TODO: (int position, int length, string str)
  225. if (str == null){Debug.Assert(false); return false;}
  226. if (str.Length != length){Debug.Assert(false); return false;}
  227. if (position < 0 || position+length > this.Length){Debug.Assert(false); return false;}
  228. unsafe{
  229. byte* p = this.AsciiStringPtr;
  230. if (p != null){
  231. for (int i = position, j = 0; j < length; i++, j++)
  232. if (((char)*(p+i)) != str[j]) return false;
  233. return true;
  234. }
  235. }
  236. string source = this.Source;
  237. if (source != null){
  238. for (int i = position, j = 0; j < length; i++, j++)
  239. if (source[i] != str[j]) return false;
  240. return true;
  241. }
  242. ISourceText myProvider = this.TextProvider;
  243. if (myProvider == null){Debug.Assert(false); return false;}
  244. for (int i = position, j = 0; j < length; i++, j++)
  245. if (myProvider[i] != str[j]) return false;
  246. return true;
  247. }
  248. /// <summary>
  249. /// Compares the substring of the specificied length starting at offset, with the substring in DocumentText starting at textOffset.
  250. /// </summary>
  251. /// <param name="offset">The index of the first character of the substring of this DocumentText.</param>
  252. /// <param name="text">The Document text with the substring being compared to.</param>
  253. /// <param name="textOffset">The index of the first character of the substring of the DocumentText being compared to.</param>
  254. /// <param name="length">The number of characters in the substring being compared.</param>
  255. /// <returns></returns>
  256. public bool Equals(int offset, DocumentText text, int textOffset, int length){ //TODO: (int position, int length, DocumentText text, int textPosition)
  257. if (offset < 0 || length < 0 || offset+length > this.Length){ Debug.Assert(false); return false;}
  258. if (textOffset < 0 || text == null || textOffset+length > text.Length){Debug.Assert(false); return false;}
  259. unsafe{
  260. byte* p = this.AsciiStringPtr;
  261. if (p != null){
  262. unsafe{
  263. byte* q = text.AsciiStringPtr;
  264. if (q != null){
  265. for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
  266. if (*(p+i) != *(q+j)) return false;
  267. return true;
  268. }
  269. }
  270. string textSource = text.Source;
  271. if (textSource != null){
  272. for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
  273. if (((char)*(p+i)) != textSource[j]) return false;
  274. return true;
  275. }
  276. ISourceText textProvider = text.TextProvider;
  277. if (textProvider == null){Debug.Assert(false); return false;}
  278. for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
  279. if (((char)*(p+i)) != textProvider[j]) return false;
  280. return true;
  281. }
  282. }
  283. string source = this.Source;
  284. if (source != null){
  285. unsafe{
  286. byte* q = text.AsciiStringPtr;
  287. if (q != null){
  288. for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
  289. if (source[i] != (char)*(q+j)) return false;
  290. return true;
  291. }
  292. }
  293. string textSource = text.Source;
  294. if (textSource != null){
  295. for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
  296. if (source[i] != textSource[j]) return false;
  297. return true;
  298. }
  299. ISourceText textProvider = text.TextProvider;
  300. if (textProvider == null){Debug.Assert(false); return false;}
  301. for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
  302. if (source[i] != textProvider[j]) return false;
  303. return true;
  304. }
  305. {
  306. ISourceText myProvider = this.TextProvider;
  307. if (myProvider == null){Debug.Assert(false); return false;}
  308. unsafe{
  309. byte* q = text.AsciiStringPtr;
  310. if (q != null){
  311. for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
  312. if (myProvider[i] != (char)*(q+j)) return false;
  313. return true;
  314. }
  315. }
  316. string textSource = text.Source;
  317. if (textSource != null){
  318. for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
  319. if (myProvider[i] != textSource[j]) return false;
  320. return true;
  321. }
  322. ISourceText textProvider = text.TextProvider;
  323. if (textProvider == null){Debug.Assert(false); return false;}
  324. for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
  325. if (myProvider[i] != textProvider[j]) return false;
  326. return true;
  327. }
  328. }
  329. /// <summary>
  330. /// Retrieves a substring from this instance. The substring starts at a specified character position and has a specified length.
  331. /// </summary>
  332. public string/*!*/ Substring(int position, int length){
  333. if (position < 0 || length < 0 || position+length > this.Length+1){Debug.Assert(false); return "";}
  334. if (position+length > this.Length) length = this.Length-position; //Allow virtual EOF character to be included in length
  335. if (this.AsciiStringPtr != null){
  336. unsafe{
  337. return new String((sbyte*)this.AsciiStringPtr, position, length, System.Text.Encoding.ASCII);
  338. }
  339. }else if (this.Source != null)
  340. return this.Source.Substring(position, length);
  341. else if (this.TextProvider != null)
  342. return this.TextProvider.Substring(position, length);
  343. else{
  344. Debug.Assert(false);
  345. return "";
  346. }
  347. }
  348. /// <summary>
  349. /// Retrieves the character at the given position. The first character is at position zero.
  350. /// </summary>
  351. public char this[int position]{
  352. get{
  353. if (position < 0 || position >= this.Length){Debug.Assert(false); return (char)0;}
  354. if (this.AsciiStringPtr != null){
  355. unsafe{
  356. unchecked{
  357. return (char) *(this.AsciiStringPtr+position);
  358. }
  359. }
  360. }else if (this.Source != null)
  361. return this.Source[position];
  362. else if (this.TextProvider != null)
  363. return this.TextProvider[position];
  364. else{
  365. Debug.Assert(false);
  366. return (char)0;
  367. }
  368. }
  369. }
  370. }
  371. /// <summary>
  372. /// A source document from which an Abstract Syntax Tree has been derived.
  373. /// </summary>
  374. public class Document{
  375. /// <summary>
  376. /// A Guid that identifies the kind of document to applications such as a debugger. Typically System.Diagnostics.SymbolStore.SymDocumentType.Text.
  377. /// </summary>
  378. public System.Guid DocumentType;
  379. /// <summary>
  380. /// A Guid that identifies the programming language used in the source document. Typically used by a debugger to locate language specific logic.
  381. /// </summary>
  382. public System.Guid Language;
  383. /// <summary>
  384. /// A Guid that identifies the compiler vendor programming language used in the source document. Typically used by a debugger to locate vendor specific logic.
  385. /// </summary>
  386. public System.Guid LanguageVendor;
  387. /// <summary>
  388. /// The line number corresponding to the first character in Text. Typically 1 but can be changed by C# preprocessor directives.
  389. /// </summary>
  390. public int LineNumber;
  391. /// <summary>
  392. /// Indicates that the document contains machine generated source code that should not show up in tools such as debuggers.
  393. /// Can be set by C# preprocessor directives.
  394. /// </summary>
  395. public bool Hidden;
  396. /// <summary>
  397. /// The name of the document. Typically a file name. Can be a full or relative file path, or a URI or some other kind of identifier.
  398. /// </summary>
  399. public string/*!*/ Name;
  400. /// <summary>
  401. /// Contains the source text.
  402. /// </summary>
  403. public DocumentText Text;
  404. public Document(){
  405. this.Name = "";
  406. //^ base();
  407. }
  408. public Document(string/*!*/ name, int lineNumber, string text, System.Guid documentType, System.Guid language, System.Guid languageVendor)
  409. :this(name, lineNumber, new DocumentText(text), documentType, language, languageVendor){
  410. }
  411. public Document(string/*!*/ name, int lineNumber, DocumentText text, System.Guid documentType, System.Guid language, System.Guid languageVendor) {
  412. this.DocumentType = documentType;
  413. this.Language = language;
  414. this.LanguageVendor = languageVendor;
  415. this.LineNumber = lineNumber;
  416. this.Name = name;
  417. this.Text = text;
  418. //^ base();
  419. }
  420. /// <summary>
  421. /// Maps the given zero based character position to the number of the source line containing the same character.
  422. /// Line number counting starts from the value of LineNumber.
  423. /// </summary>
  424. public virtual int GetLine(int position){
  425. int line = 0; int column = 0;
  426. this.GetPosition(position, out line, out column);
  427. return line+this.LineNumber;
  428. }
  429. /// <summary>
  430. /// Maps the given zero based character position in the entire text to the position of the same character in a source line.
  431. /// Counting within the source line starts at 1.
  432. /// </summary>
  433. public virtual int GetColumn(int position){
  434. int line = 0; int column = 0;
  435. this.GetPosition(position, out line, out column);
  436. return column+1;
  437. }
  438. /// <summary>
  439. /// Given a startLine, startColum, endLine and endColumn, this returns the corresponding startPos and endPos. In other words it
  440. /// converts a range expression in line and columns to a range expressed as a start and end character position.
  441. /// </summary>
  442. /// <param name="startLine">The number of the line containing the first character. The number of the first line equals this.LineNumber.</param>
  443. /// <param name="startColumn">The position of the first character relative to the start of the line. Counting from 1.</param>
  444. /// <param name="endLine">The number of the line contain the character that immediate follows the last character of the range.</param>
  445. /// <param name="endColumn">The position, in the last line, of the character that immediately follows the last character of the range.</param>
  446. /// <param name="startPos">The position in the entire text of the first character of the range, counting from 0.</param>
  447. /// <param name="endPos">The position in the entire text of the character following the last character of the range.</param>
  448. public virtual void GetOffsets(int startLine, int startColumn, int endLine, int endColumn, out int startPos, out int endPos){
  449. lock(this){
  450. if (this.lineOffsets == null) this.ComputeLineOffsets();
  451. //^ assert this.lineOffsets != null;
  452. startPos = this.lineOffsets[startLine-this.LineNumber]+startColumn-1;
  453. endPos = this.lineOffsets[endLine-this.LineNumber]+endColumn-1;
  454. }
  455. }
  456. /// <summary>
  457. /// Retrieves a substring from the text of this Document. The substring starts at a specified character position and has a specified length.
  458. /// </summary>
  459. public virtual string Substring(int position, int length){
  460. if (this.Text == null) return null;
  461. return this.Text.Substring(position, length);
  462. }
  463. /// <summary>
  464. /// Counts the number of end of line marker sequences in the given text.
  465. /// </summary>
  466. protected int GetLineCount(string/*!*/ text) {
  467. int n = text == null ? 0 : text.Length;
  468. int count = 0;
  469. for (int i = 0; i < n; i++){
  470. switch(text[i]){
  471. case '\r':
  472. if (i+1 < n && text[i+1] == '\n')
  473. i++;
  474. count++;
  475. break;
  476. case '\n':
  477. case (char)0x2028:
  478. case (char)0x2029:
  479. count++;
  480. break;
  481. }
  482. }
  483. return count;
  484. }
  485. /// <summary>An array of offsets, with offset at index i corresponding to the position of the first character of line i, (counting lines from 0).</summary>
  486. private int[] lineOffsets;
  487. /// <summary>The number of lines in Text.</summary>
  488. private int lines;
  489. /// <summary>
  490. /// Returns the index in this.lineOffsets array such that this.lineOffsets[index] is less than or equal to offset
  491. /// and offset is less than lineOffsets[index+1]
  492. /// </summary>
  493. private int Search(int offset){
  494. tryAgain:
  495. int[] lineOffsets = this.lineOffsets;
  496. int lines = this.lines;
  497. if (lineOffsets == null){Debug.Assert(false); return -1;}
  498. if (offset < 0){Debug.Assert(false); return -1;}
  499. int mid = 0;
  500. int low = 0;
  501. int high = lines-1;
  502. while (low < high){
  503. mid = (low+high)/2;
  504. if (lineOffsets[mid] <= offset){
  505. if (offset < lineOffsets[mid+1])
  506. return mid;
  507. else
  508. low = mid + 1;
  509. }else
  510. high = mid;
  511. }
  512. Debug.Assert(lines == this.lines);
  513. Debug.Assert(lineOffsets[low] <= offset);
  514. Debug.Assert(offset < lineOffsets[low+1]);
  515. if (lineOffsets != this.lineOffsets) goto tryAgain;
  516. return low;
  517. }
  518. /// <summary>
  519. /// Maps the given zero based character position in the entire text to a (line, column) pair corresponding to the same position.
  520. /// Counting within the source line starts at 0. Counting source lines start at 0.
  521. /// </summary>
  522. private void GetPosition(int offset, out int line, out int column){
  523. line = 0; column = 0;
  524. if (offset < 0 || this.Text == null || offset > this.Text.Length){Debug.Assert(false); return;}
  525. lock(this){
  526. if (this.lineOffsets == null) this.ComputeLineOffsets();
  527. if (this.lineOffsets == null){Debug.Assert(false); return;}
  528. int[] lineOffsets = this.lineOffsets;
  529. int index = this.Search(offset);
  530. Debug.Assert(lineOffsets == this.lineOffsets);
  531. if (index < 0 || index >= this.lineOffsets.Length){Debug.Assert(false); return;}
  532. Debug.Assert(this.lineOffsets[index] <= offset && offset < this.lineOffsets[index+1]);
  533. line = index;
  534. column = offset-this.lineOffsets[index];
  535. }
  536. }
  537. /// <summary>
  538. /// Adds the given offset to the this.lineOffsets table as the offset corresponding to the start of line this.lines+1.
  539. /// </summary>
  540. private void AddOffset(int offset){
  541. if (this.lineOffsets == null || this.lines < 0){Debug.Assert(false); return;}
  542. if (this.lines >= this.lineOffsets.Length){
  543. int n = this.lineOffsets.Length;
  544. if (n <= 0) n = 16;
  545. int[] newLineOffsets = new int[n*2];
  546. Array.Copy(this.lineOffsets, newLineOffsets, this.lineOffsets.Length);
  547. this.lineOffsets = newLineOffsets;
  548. }
  549. this.lineOffsets[this.lines++] = offset;
  550. }
  551. public virtual void InsertOrDeleteLines(int offset, int lineCount){
  552. if (lineCount == 0) return;
  553. if (offset < 0 || this.Text == null || offset > this.Text.Length){Debug.Assert(false); return;}
  554. lock(this){
  555. if (this.lineOffsets == null)
  556. if (this.lineOffsets == null) this.ComputeLineOffsets();
  557. if (lineCount < 0)
  558. this.DeleteLines(offset, -lineCount);
  559. else
  560. this.InsertLines(offset, lineCount);
  561. }
  562. }
  563. private void DeleteLines(int offset, int lineCount)
  564. //^ requires offset >= 0 && this.Text != null && offset < this.Text.Length && lineCount > 0 && this.lineOffsets != null;
  565. {
  566. Debug.Assert(offset >= 0 && this.Text != null && offset < this.Text.Length && lineCount > 0 && this.lineOffsets != null);
  567. int index = this.Search(offset);
  568. if (index < 0 || index >= this.lines){Debug.Assert(false); return;}
  569. for (int i = index+1; i+lineCount < this.lines; i++){
  570. this.lineOffsets[i] = this.lineOffsets[i+lineCount];
  571. }
  572. this.lines -= lineCount;
  573. if (this.lines <= index){Debug.Assert(false); this.lines = index+1;}
  574. }
  575. private void InsertLines(int offset, int lineCount)
  576. //^ requires offset >= 0 && this.Text != null && offset < this.Text.Length && lineCount > 0 && this.lineOffsets != null;
  577. {
  578. Debug.Assert(offset >= 0 && this.Text != null && offset < this.Text.Length && lineCount > 0 && this.lineOffsets != null);
  579. int index = this.Search(offset);
  580. if (index < 0 || index >= this.lines){Debug.Assert(false); return;}
  581. int n = this.lineOffsets[this.lines-1];
  582. for (int i = 0; i < lineCount; i++) this.AddOffset(++n);
  583. for (int i = lineCount; i > 0; i--){
  584. this.lineOffsets[index+i+1] = this.lineOffsets[index+1];
  585. }
  586. }
  587. /// <summary>
  588. /// Populates this.lineOffsets with an array of offsets, with offset at index i corresponding to the position of the first
  589. /// character of line i, (counting lines from 0).
  590. /// </summary>
  591. private void ComputeLineOffsets()
  592. //ensures this.lineOffsets != null;
  593. {
  594. if (this.Text == null){Debug.Assert(false); return;}
  595. int n = this.Text.Length;
  596. this.lineOffsets = new int[n/10+1];
  597. this.lines = 0;
  598. this.AddOffset(0);
  599. for (int i = 0; i < n; i++){
  600. switch(this.Text[i]){
  601. case '\r':
  602. if (i+1 < n && this.Text[i+1] == '\n')
  603. i++;
  604. this.AddOffset(i+1);
  605. break;
  606. case '\n':
  607. case (char)0x2028:
  608. case (char)0x2029:
  609. this.AddOffset(i+1);
  610. break;
  611. }
  612. }
  613. this.AddOffset(n+1);
  614. this.AddOffset(n+2);
  615. }
  616. /// <summary> Add one to this every time a Document instance gets a unique key.</summary>
  617. private static int uniqueKeyCounter;
  618. private int uniqueKey;
  619. /// <summary>
  620. /// An integer that uniquely distinguishes this document instance from every other document instance.
  621. /// This provides an efficient equality test to facilitate hashing.
  622. /// </summary>
  623. public int UniqueKey{
  624. get{
  625. if (this.uniqueKey == 0){
  626. TryAgain:
  627. int c = Document.uniqueKeyCounter;
  628. int cp1 = c == int.MaxValue ? 1 : c+1;
  629. if (System.Threading.Interlocked.CompareExchange(ref Document.uniqueKeyCounter, cp1, c) != c) goto TryAgain;
  630. this.uniqueKey = cp1;
  631. }
  632. return this.uniqueKey;
  633. }
  634. }
  635. }
  636. #endif
  637. #if !MinimalReader
  638. /// <summary>
  639. /// For creating source contexts that have just a filename, start line and column and end line and column.
  640. /// If a SourceContext has a DocumentWithPrecomputedLineNumbers as its Document, then it should have 0 as its StartPos
  641. /// and 1 as its EndPos because those are used here to decide what to return.
  642. /// </summary>
  643. public class DocumentWithPrecomputedLineNumbers : Document {
  644. private int startLine, startCol, endLine, endCol;
  645. public DocumentWithPrecomputedLineNumbers(string/*!*/ filename, int startLine, int startCol, int endLine, int endCol) {
  646. this.Name = filename;
  647. this.startLine = startLine;
  648. this.startCol = startCol;
  649. this.endLine = endLine;
  650. this.endCol = endCol;
  651. }
  652. public override int GetColumn (int offset) { return offset == 0 ? this.startCol : this.endCol; }
  653. public override int GetLine (int offset) { return offset == 0 ? this.startLine : this.endLine; }
  654. }
  655. #endif
  656. #if UseSingularityPDB
  657. internal class PdbDocument : Document {
  658. internal PdbDocument(PdbLines lines) {
  659. this.Name = lines.file.name;
  660. this.lines = lines;
  661. }
  662. PdbLines lines;
  663. public override int GetColumn(int position) {
  664. PdbLine line = this.lines.lines[position/2];
  665. if (position%2 == 0)
  666. return line.colBegin;
  667. else
  668. return line.colEnd;
  669. }
  670. public override int GetLine(int position) {
  671. PdbLine line = this.lines.lines[position/2];
  672. return (int)line.line;
  673. }
  674. }
  675. #elif !ROTOR
  676. internal class UnmanagedDocument: Document{
  677. internal UnmanagedDocument(IntPtr ptrToISymUnmanagedDocument){
  678. //^ base();
  679. ISymUnmanagedDocument idoc =
  680. (ISymUnmanagedDocument)System.Runtime.InteropServices.Marshal.GetTypedObjectForIUnknown(ptrToISymUnmanagedDocument, typeof(ISymUnmanagedDocument));
  681. if (idoc != null){
  682. try{
  683. #if !FxCop
  684. idoc.GetDocumentType(out this.DocumentType);
  685. idoc.GetLanguage(out this.Language);
  686. idoc.GetLanguageVendor(out this.LanguageVendor);
  687. #endif
  688. uint capacity = 1024;
  689. uint len = 0;
  690. char[] buffer = new char[capacity];
  691. while (capacity >= 1024){
  692. idoc.GetURL(capacity, out len, buffer);
  693. if (len < capacity) break;
  694. capacity += 1024;
  695. buffer = new char[capacity];
  696. }
  697. if (len > 0)
  698. this.Name = new String(buffer, 0, (int)len-1);
  699. }finally{
  700. System.Runtime.InteropServices.Marshal.ReleaseComObject(idoc);
  701. }
  702. }
  703. #if !FxCop
  704. this.LineNumber = -1;
  705. this.Text = null;
  706. #endif
  707. }
  708. private Int32List/*!*/ lineList = new Int32List();
  709. private Int32List/*!*/ columnList = new Int32List();
  710. #if !FxCop
  711. public override int GetLine(int offset){
  712. return this.lineList[offset];
  713. }
  714. public override int GetColumn(int offset){
  715. return this.columnList[offset];
  716. }
  717. public override void GetOffsets(int startLine, int startColumn, int endLine, int endColumn, out int startCol, out int endCol){
  718. int i = UnmanagedDocument.BinarySearch(this.lineList, startLine);
  719. Int32List columnList = this.columnList;
  720. startCol = 0;
  721. for (int j = i, n = columnList.Count; j < n; j++){
  722. if (columnList[j] >= startColumn){ startCol = j; break;}
  723. }
  724. endCol = 0;
  725. i = UnmanagedDocument.BinarySearch(this.lineList, endLine);
  726. for (int j = i, n = columnList.Count; j < n; j++){
  727. if (columnList[j] >= endColumn){ endCol = j; break;}
  728. }
  729. }
  730. private static int BinarySearch(Int32List/*!*/ list, int value){
  731. int mid = 0;
  732. int low = 0;
  733. int high = list.Count-1;
  734. while (low < high){
  735. mid = low + (high-low)/2;
  736. if (list[mid] <= value){
  737. if (list[mid+1] > value)
  738. return mid;
  739. else
  740. low = mid + 1;
  741. }else
  742. high = mid;
  743. }
  744. return low;
  745. }
  746. public override void InsertOrDeleteLines(int offset, int lineCount){
  747. Debug.Assert(false); //Caller should not be modifying an umanaged document
  748. }
  749. #endif
  750. internal int GetOffset(uint line, uint column){
  751. this.lineList.Add((int)line);
  752. this.columnList.Add((int)column);
  753. return this.lineList.Count-1;
  754. }
  755. }
  756. #endif // !ROTOR
  757. #if FxCop
  758. class Document{
  759. internal string Name;
  760. }
  761. public struct SourceContext{
  762. private string name;
  763. private int startLine;
  764. private int endLine;
  765. private int startColumn;
  766. private int endColumn;
  767. internal SourceContext(string name, uint startLine, uint endLine, uint startColumn, uint endColumn){
  768. this.name = name;
  769. checked {
  770. this.startLine = (int)startLine;
  771. this.endLine = (int)endLine;
  772. this.startColumn = (int)startColumn;
  773. this.endColumn = (int)endColumn;
  774. }
  775. }
  776. public string FileName{
  777. get{return this.name;}
  778. }
  779. public int StartLine{
  780. get{return this.startLine;}
  781. }
  782. public int EndLine{
  783. get{return this.endLine;}
  784. }
  785. public int StartColumn{
  786. get{return this.startColumn;}
  787. }
  788. public int EndColumn{
  789. get{return this.endColumn;}
  790. }
  791. }
  792. #else
  793. /// <summary>
  794. /// Records a location within a source document that corresponds to an Abstract Syntax Tree node.
  795. /// </summary>
  796. public struct SourceContext{
  797. /// <summary>The source document within which the AST node is located. Null if the node is not derived from a source document.</summary>
  798. public Document Document;
  799. /// <summary>
  800. /// The zero based index of the first character beyond the last character in the source document that corresponds to the AST node.
  801. /// </summary>
  802. public int EndPos;
  803. /// <summary>
  804. /// The zero based index of the first character in the source document that corresponds to the AST node.
  805. /// </summary>
  806. public int StartPos;
  807. public SourceContext(Document document)
  808. : this(document, 0, document == null ? 0 : (document.Text == null ? 0 : document.Text.Length)){
  809. }
  810. public SourceContext(Document document, int startPos, int endPos){
  811. this.Document = document;
  812. this.StartPos = startPos;
  813. this.EndPos = endPos;
  814. }
  815. public SourceContext(Document/*!*/ document,
  816. int startLine, int startColumn, int endLine, int endColumn){
  817. this.Document = document;
  818. this.Document.GetOffsets(startLine, startColumn, endLine, endColumn, out this.StartPos, out this.EndPos);
  819. }
  820. /// <summary>
  821. /// The number (counting from Document.LineNumber) of the line containing the first character in the source document that corresponds to the AST node.
  822. /// </summary>
  823. public int StartLine{
  824. get{
  825. if (this.Document == null) return 0;
  826. return this.Document.GetLine(this.StartPos);
  827. }
  828. }
  829. /// <summary>
  830. /// The number (counting from one) of the line column containing the first character in the source document that corresponds to the AST node.
  831. /// </summary>
  832. public int StartColumn{
  833. get{
  834. if (this.Document == null) return 0;
  835. return this.Document.GetColumn(this.StartPos);
  836. }
  837. }
  838. /// <summary>
  839. /// The number (counting from Document.LineNumber) of the line containing the first character beyond the last character in the source document that corresponds to the AST node.
  840. /// </summary>
  841. public int EndLine{
  842. get{
  843. #if UseSingularityPDB
  844. if (this.Document == null || (this.Document.Text == null && !(this.Document is PdbDocument))) return 0;
  845. #elif !ROTOR
  846. if (this.Document == null || (this.Document.Text == null && !(this.Document is UnmanagedDocument))) return 0;
  847. #else
  848. if (this.Document == null || this.Document.Text == null) return 0;
  849. #endif
  850. if (this.Document.Text != null && this.EndPos >= this.Document.Text.Length) this.EndPos = this.Document.Text.Length;
  851. return this.Document.GetLine(this.EndPos);
  852. }
  853. }
  854. /// <summary>
  855. /// The number (counting from one) of the line column containing first character beyond the last character in the source document that corresponds to the AST node.
  856. /// </summary>
  857. public int EndColumn{
  858. get{
  859. #if UseSingularityPDB
  860. if (this.Document == null || (this.Document.Text == null && !(this.Document is PdbDocument))) return 0;
  861. #elif !ROTOR
  862. if (this.Document == null || (this.Document.Text == null && !(this.Document is UnmanagedDocument))) return 0;
  863. #else
  864. if (this.Document == null || this.Document.Text == null) return 0;
  865. #endif
  866. if (this.Document.Text != null && this.EndPos >= this.Document.Text.Length) this.EndPos = this.Document.Text.Length;
  867. return this.Document.GetColumn(this.EndPos);
  868. }
  869. }
  870. /// <summary>
  871. /// Returns true if the line and column is greater than or equal the position of the first character
  872. /// and less than or equal to the position of the last character
  873. /// of the source document that corresponds to the AST node.
  874. /// </summary>
  875. /// <param name="line">A line number(counting from Document.LineNumber)</param>
  876. /// <param name="column">A column number (counting from one)</param>
  877. /// <returns></returns>
  878. public bool Encloses(int line, int column){
  879. if (line < this.StartLine || line > this.EndLine) return false;
  880. if (line == this.StartLine) return column >= this.StartColumn && (column <= this.EndColumn || line < this.EndLine);
  881. if (line == this.EndLine) return column <= this.EndColumn;
  882. return true;
  883. }
  884. public bool Encloses(SourceContext sourceContext){
  885. return this.StartPos <= sourceContext.StartPos && this.EndPos >= sourceContext.EndPos && this.EndPos > sourceContext.StartPos;
  886. }
  887. /// <summary>
  888. /// The substring of the source document that corresponds to the AST node.
  889. /// </summary>
  890. public string SourceText{
  891. get{
  892. if (this.Document == null) return null;
  893. return this.Document.Substring(this.StartPos, this.EndPos-this.StartPos);
  894. }
  895. }
  896. }
  897. #endif
  898. #if !MinimalReader
  899. public struct SourceChange{
  900. public SourceContext SourceContext;
  901. public string ChangedText;
  902. }
  903. /// <summary>
  904. /// Allows a compilation to output progress messages and to query if cancellation was requested.
  905. /// </summary>
  906. public class CompilerSite{
  907. public virtual void OutputMessage(string message){
  908. }
  909. public virtual bool ShouldCancel{
  910. get{
  911. return false;
  912. }
  913. }
  914. }
  915. #endif
  916. #if !NoWriter
  917. public enum PlatformType{notSpecified, v1, v11, v2, cli1}
  918. public class CompilerOptions: System.CodeDom.Compiler.CompilerParameters{
  919. public StringCollection AliasesForReferencedAssemblies;
  920. public ModuleKindFlags ModuleKind = ModuleKindFlags.ConsoleApplication;
  921. public bool EmitManifest = true;
  922. public StringList DefinedPreProcessorSymbols;
  923. public string XMLDocFileName;
  924. public string RecursiveWildcard;
  925. public StringList ReferencedModules;
  926. public string Win32Icon;
  927. #if !WHIDBEY
  928. private StringCollection embeddedResources = new StringCollection();
  929. public StringCollection EmbeddedResources{
  930. get{return this.embeddedResources;}
  931. }
  932. private StringCollection linkedResources = new StringCollection();
  933. public StringCollection LinkedResources{
  934. get{return this.linkedResources;}
  935. }
  936. #endif
  937. #if VS7
  938. private System.Security.Policy.Evidence evidence;
  939. public System.Security.Policy.Evidence Evidence{
  940. get{return this.evidence;}
  941. set{this.evidence = value;}
  942. }
  943. #endif
  944. public bool PDBOnly;
  945. public bool Optimize;
  946. public bool IncrementalCompile;
  947. public Int32List SuppressedWarnings;
  948. public bool CheckedArithmetic;
  949. public bool AllowUnsafeCode;
  950. public bool DisplayCommandLineHelp;
  951. public bool SuppressLogo;
  952. public long BaseAddress; //TODO: default value
  953. public string BugReportFileName;
  954. public object CodePage; //must be an int if not null
  955. public bool EncodeOutputInUTF8;
  956. public bool FullyQualifyPaths;
  957. public int FileAlignment;
  958. public bool NoStandardLibrary;
  959. public StringList AdditionalSearchPaths;
  960. public bool HeuristicReferenceResolution;
  961. public string RootNamespace;
  962. public bool CompileAndExecute;
  963. public object UserLocaleId; //must be an int if not null
  964. public string StandardLibraryLocation;
  965. public PlatformType TargetPlatform; //TODO: rename this to TargetRuntime
  966. #if !MinimalReader
  967. public ProcessorType TargetProcessor;
  968. #endif
  969. public string TargetPlatformLocation;
  970. public string AssemblyKeyFile;
  971. public string AssemblyKeyName;
  972. public bool DelaySign;
  973. public TargetInformation TargetInformation;
  974. public Int32List SpecificWarningsToTreatAsErrors;
  975. public Int32List SpecificWarningsNotToTreatAsErrors;
  976. public string OutputPath;
  977. public string ExplicitOutputExtension;
  978. public AppDomain TargetAppDomain;
  979. public bool MayLockFiles;
  980. public string ShadowedAssembly;
  981. public bool UseStandardConfigFile;
  982. #if !MinimalReader
  983. public CompilerSite Site;
  984. #endif
  985. #if ExtendedRuntime
  986. /// <summary>
  987. /// True if the source code for the assembly specify only contracts.
  988. /// </summary>
  989. public bool IsContractAssembly;
  990. /// <summary>
  991. /// Do not emit run-time checks for requires clauses of non-externally-accessible methods, assert statements, loop invariants, and ensures clauses.
  992. /// </summary>
  993. public bool DisableInternalChecks;
  994. /// <summary>
  995. /// Do not emit run-time checks for assume statements.
  996. /// </summary>
  997. public bool DisableAssumeChecks;
  998. /// <summary>
  999. /// Do not emit run-time checks for requires clauses of externally accessible methods.
  1000. /// Do not emit run-time checks that enforce checked exception policy.
  1001. /// </summary>
  1002. public bool DisableDefensiveChecks;
  1003. /// <summary>
  1004. /// Disable the guarded classes feature, which integrates run-time enforcement of object invariants, ownership, and safe concurrency.
  1005. /// </summary>
  1006. public bool DisableGuardedClassesChecks;
  1007. public bool DisableInternalContractsMetadata;
  1008. public bool DisablePublicContractsMetadata;
  1009. /// <summary>
  1010. /// Disable the runtime test against null on non-null typed parameters on public methods
  1011. /// </summary>
  1012. public bool DisableNullParameterValidation;
  1013. public virtual bool LoadDebugSymbolsForReferencedAssemblies {
  1014. get { return false; }
  1015. }
  1016. /// <summary>
  1017. /// If set, the compiler will only parse and then emit an xml file with detailed source contexts
  1018. /// about what is parsed.
  1019. /// </summary>
  1020. public bool EmitSourceContextsOnly = false;
  1021. #endif
  1022. public CompilerOptions(){
  1023. }
  1024. public CompilerOptions(CompilerOptions source){
  1025. if (source == null){Debug.Assert(false); return;}
  1026. this.AdditionalSearchPaths = source.AdditionalSearchPaths; //REVIEW: clone the list?
  1027. this.AliasesForReferencedAssemblies = source.AliasesForReferencedAssemblies;
  1028. this.AllowUnsafeCode = source.AllowUnsafeCode;
  1029. this.AssemblyKeyFile = source.AssemblyKeyFile;
  1030. this.AssemblyKeyName = source.AssemblyKeyName;
  1031. this.BaseAddress = source.BaseAddress;
  1032. this.BugReportFileName = source.BugReportFileName;
  1033. this.CheckedArithmetic = source.CheckedArithmetic;
  1034. this.CodePage = source.CodePage;
  1035. this.CompileAndExecute = source.CompileAndExecute;
  1036. this.CompilerOptions = source.CompilerOptions;
  1037. this.DefinedPreProcessorSymbols = source.DefinedPreProcessorSymbols;
  1038. this.DelaySign = source.DelaySign;
  1039. #if ExtendedRuntime
  1040. this.DisableAssumeChecks = source.DisableAssumeChecks;
  1041. this.DisableDefensiveChecks = source.DisableDefensiveChecks;
  1042. this.DisableGuardedClassesChecks = source.DisableGuardedClassesChecks;
  1043. this.DisableInternalChecks = source.DisableInternalChecks;
  1044. this.DisableInternalContractsMetadata = source.DisableInternalContractsMetadata;
  1045. this.DisablePublicContractsMetadata = source.DisablePublicContractsMetadata;
  1046. #endif
  1047. this.DisplayCommandLineHelp = source.DisplayCommandLineHelp;
  1048. if (source.EmbeddedResources != null)
  1049. foreach (string s in source.EmbeddedResources) this.EmbeddedResources.Add(s);
  1050. this.EmitManifest = source.EmitManifest;
  1051. this.EncodeOutputInUTF8 = source.EncodeOutputInUTF8;
  1052. this.Evidence = source.Evidence;
  1053. this.ExplicitOutputExtension = source.ExplicitOutputExtension;
  1054. this.FileAlignment = source.FileAlignment;
  1055. this.FullyQualifyPaths = source.FullyQualifyPaths;
  1056. this.GenerateExecutable = source.GenerateExecutable;
  1057. this.GenerateInMemory = source.GenerateInMemory;
  1058. this.HeuristicReferenceResolution = source.HeuristicReferenceResolution;
  1059. this.IncludeDebugInformation = source.IncludeDebugInformation;
  1060. this.IncrementalCompile = source.IncrementalCompile;
  1061. #if ExtendedRuntime
  1062. this.IsContractAssembly = source.IsContractAssembly;
  1063. #endif
  1064. if (source.LinkedResources != null)
  1065. foreach (string s in source.LinkedResources) this.LinkedResources.Add(s);
  1066. this.MainClass = source.MainClass;
  1067. this.MayLockFiles = source.MayLockFiles;
  1068. this.ModuleKind = source.ModuleKind;
  1069. this.NoStandardLibrary = source.NoStandardLibrary;
  1070. this.Optimize = source.Optimize;
  1071. this.OutputAssembly = source.OutputAssembly;
  1072. this.OutputPath = source.OutputPath;
  1073. this.PDBOnly = source.PDBOnly;
  1074. this.RecursiveWildcard = source.RecursiveWildcard;
  1075. if (source.ReferencedAssemblies != null)
  1076. foreach (string s in source.ReferencedAssemblies) this.ReferencedAssemblies.Add(s);
  1077. this.ReferencedModules = source.ReferencedModules;
  1078. this.RootNamespace = source.RootNamespace;
  1079. this.ShadowedAssembly = source.ShadowedAssembly;
  1080. this.SpecificWarningsToTreatAsErrors = source.SpecificWarningsToTreatAsErrors;
  1081. this.StandardLibraryLocation = source.StandardLibraryLocation;
  1082. this.SuppressLogo = source.SuppressLogo;
  1083. this.SuppressedWarnings = source.SuppressedWarnings;
  1084. this.TargetAppDomain = source.TargetAppDomain;
  1085. this.TargetInformation = source.TargetInformation;
  1086. this.TargetPlatform = source.TargetPlatform;
  1087. this.TargetPlatformLocation = source.TargetPlatformLocation;
  1088. this.TreatWarningsAsErrors = source.TreatWarningsAsErrors;
  1089. this.UserLocaleId = source.UserLocaleId;
  1090. this.UserToken = source.UserToken;
  1091. this.WarningLevel = source.WarningLevel;
  1092. this.Win32Icon = source.Win32Icon;
  1093. this.Win32Resource = source.Win32Resource;
  1094. this.XMLDocFileName = source.XMLDocFileName;
  1095. }
  1096. public virtual string GetOptionHelp(){
  1097. return null;
  1098. }
  1099. public virtual CompilerOptions Clone() {
  1100. return (CompilerOptions)this.MemberwiseClone();
  1101. }
  1102. }
  1103. #endif
  1104. public sealed class MarshallingInformation{
  1105. private string @class;
  1106. private string cookie;
  1107. private int elementSize;
  1108. private NativeType elementType;
  1109. private NativeType nativeType;
  1110. private int numberOfElements;
  1111. private int paramIndex;
  1112. private int size;
  1113. public MarshallingInformation Clone(){
  1114. return (MarshallingInformation)base.MemberwiseClone();
  1115. }
  1116. public string Class{
  1117. get{return this.@class;}
  1118. set{this.@class = value;}
  1119. }
  1120. public string Cookie{
  1121. get{return this.cookie;}
  1122. set{this.cookie = value;}
  1123. }
  1124. public int ElementSize{
  1125. get{return this.elementSize;}
  1126. set{this.elementSize = value;}
  1127. }
  1128. public NativeType ElementType{
  1129. get{return this.elementType;}
  1130. set{this.elementType = value;}
  1131. }
  1132. public NativeType NativeType{
  1133. get{return this.nativeType;}
  1134. set{this.nativeType = value;}
  1135. }
  1136. public int NumberOfElements{
  1137. get{return this.numberOfElements;}
  1138. set{this.numberOfElements = value;}
  1139. }
  1140. public int ParamIndex{
  1141. get{return this.paramIndex;}
  1142. set{this.paramIndex = value;}
  1143. }
  1144. public int Size{
  1145. get{return this.size;}
  1146. set{this.size = value;}
  1147. }
  1148. }
  1149. #if !NoWriter
  1150. public struct TargetInformation{
  1151. public string Company;
  1152. public string Configuration;
  1153. public string Copyright;
  1154. public string Culture;
  1155. public string Description;
  1156. public string Product;
  1157. public string ProductVersion;
  1158. public string Title;
  1159. public string Trademark;
  1160. public string Version;
  1161. }
  1162. #endif
  1163. public enum NativeType{
  1164. Bool = 0x2, // 4 byte boolean value (true != 0, false == 0)
  1165. I1 = 0x3, // 1 byte signed value
  1166. U1 = 0x4, // 1 byte unsigned value
  1167. I2 = 0x5, // 2 byte signed value
  1168. U2 = 0x6, // 2 byte unsigned value
  1169. I4 = 0x7, // 4 byte signed value
  1170. U4 = 0x8, // 4 byte unsigned value
  1171. I8 = 0x9, // 8 byte signed value
  1172. U8 = 0xa, // 8 byte unsigned value
  1173. R4 = 0xb, // 4 byte floating point
  1174. R8 = 0xc, // 8 byte floating point
  1175. Currency = 0xf, // A currency
  1176. BStr = 0x13, // OLE Unicode BSTR
  1177. LPStr = 0x14, // Ptr to SBCS string
  1178. LPWStr = 0x15, // Ptr to Unicode string
  1179. LPTStr = 0x16, // Ptr to OS preferred (SBCS/Unicode) string
  1180. ByValTStr = 0x17, // OS preferred (SBCS/Unicode) inline string (only valid in structs)
  1181. IUnknown = 0x19, // COM IUnknown pointer.
  1182. IDispatch = 0x1a, // COM IDispatch pointer
  1183. Struct = 0x1b, // Structure
  1184. Interface = 0x1c, // COM interface
  1185. SafeArray = 0x1d, // OLE SafeArray
  1186. ByValArray = 0x1e, // Array of fixed size (only valid in structs)
  1187. SysInt = 0x1f, // Hardware natural sized signed integer
  1188. SysUInt = 0x20,
  1189. VBByRefStr = 0x22,
  1190. AnsiBStr = 0x23, // OLE BSTR containing SBCS characters
  1191. TBStr = 0x24, // Ptr to OS preferred (SBCS/Unicode) BSTR
  1192. VariantBool = 0x25, // OLE defined BOOLEAN (2 bytes, true == -1, false == 0)
  1193. FunctionPtr = 0x26, // Function pointer
  1194. AsAny = 0x28, // Paired with Object type and does runtime marshalling determination
  1195. LPArray = 0x2a, // C style array
  1196. LPStruct = 0x2b, // Pointer to a structure
  1197. CustomMarshaler = 0x2c, // Native type supplied by custom code
  1198. Error = 0x2d,
  1199. NotSpecified = 0x50,
  1200. }
  1201. ///0-: Common
  1202. ///1000-: HScript
  1203. ///2000-: EcmaScript
  1204. ///3000-: Zonnon
  1205. ///4000-: Comega
  1206. ///5000-: X++
  1207. ///6000-: Spec#
  1208. ///7000-: Sing#
  1209. ///8000-: Xaml
  1210. ///9000-: C/AL
  1211. ///For your range contact hermanv@microsoft.com
  1212. public enum NodeType {
  1213. //Dummy
  1214. Undefined = 0,
  1215. //IL instruction node tags
  1216. Add,
  1217. Add_Ovf,
  1218. Add_Ovf_Un,
  1219. And,
  1220. Arglist,
  1221. Box,
  1222. Branch,
  1223. Call,
  1224. Calli,
  1225. Callvirt,
  1226. Castclass,
  1227. Ceq,
  1228. Cgt,
  1229. Cgt_Un,
  1230. Ckfinite,
  1231. Clt,
  1232. Clt_Un,
  1233. Conv_I,
  1234. Conv_I1,
  1235. Conv_I2,
  1236. Conv_I4,
  1237. Conv_I8,
  1238. Conv_Ovf_I,
  1239. Conv_Ovf_I_Un,
  1240. Conv_Ovf_I1,
  1241. Conv_Ovf_I1_Un,
  1242. Conv_Ovf_I2,
  1243. Conv_Ovf_I2_Un,
  1244. Conv_Ovf_I4,
  1245. Conv_Ovf_I4_Un,
  1246. Conv_Ovf_I8,
  1247. Conv_Ovf_I8_Un,
  1248. Conv_Ovf_U,
  1249. Conv_Ovf_U_Un,
  1250. Conv_Ovf_U1,
  1251. Conv_Ovf_U1_Un,
  1252. Conv_Ovf_U2,
  1253. Conv_Ovf_U2_Un,
  1254. Conv_Ovf_U4,
  1255. Conv_Ovf_U4_Un,
  1256. Conv_Ovf_U8,
  1257. Conv_Ovf_U8_Un,
  1258. Conv_R_Un,
  1259. Conv_R4,
  1260. Conv_R8,
  1261. Conv_U,
  1262. Conv_U1,
  1263. Conv_U2,
  1264. Conv_U4,
  1265. Conv_U8,
  1266. Cpblk,
  1267. DebugBreak,
  1268. Div,
  1269. Div_Un,
  1270. Dup,
  1271. EndFilter,
  1272. EndFinally,
  1273. ExceptionHandler,
  1274. Initblk,
  1275. Isinst,
  1276. Jmp,
  1277. Ldftn,
  1278. Ldlen,
  1279. Ldtoken,
  1280. Ldvirtftn,
  1281. Localloc,
  1282. Mkrefany,
  1283. Mul,
  1284. Mul_Ovf,
  1285. Mul_Ovf_Un,
  1286. Neg,
  1287. Nop,
  1288. Not,
  1289. Or,
  1290. Pop,
  1291. ReadOnlyAddressOf,
  1292. Refanytype,
  1293. Refanyval,
  1294. Rem,
  1295. Rem_Un,
  1296. Rethrow,
  1297. Shl,
  1298. Shr,
  1299. Shr_Un,
  1300. Sizeof,
  1301. SkipCheck,
  1302. Sub,
  1303. Sub_Ovf,
  1304. Sub_Ovf_Un,
  1305. SwitchInstruction,
  1306. Throw,
  1307. Unbox,
  1308. UnboxAny,
  1309. Xor,
  1310. //AST tags that are relevant to the binary reader
  1311. AddressDereference,
  1312. AddressOf,
  1313. AssignmentStatement,
  1314. Block,
  1315. Catch,
  1316. Construct,
  1317. ConstructArray,
  1318. Eq,
  1319. ExpressionStatement,
  1320. FaultHandler,
  1321. Filter,
  1322. Finally,
  1323. Ge,
  1324. Gt,
  1325. Identifier,
  1326. Indexer,
  1327. Instruction,
  1328. InterfaceExpression,
  1329. Le,
  1330. Literal,
  1331. LogicalNot,
  1332. Lt,
  1333. MemberBinding,
  1334. NamedArgument,
  1335. Namespace,
  1336. Ne,
  1337. Return,
  1338. This,
  1339. Try,
  1340. //Metadata node tags
  1341. ArrayType,
  1342. @Assembly,
  1343. AssemblyReference,
  1344. Attribute,
  1345. Class,
  1346. ClassParameter,
  1347. DelegateNode,
  1348. EnumNode,
  1349. Event,
  1350. Field,
  1351. FunctionPointer,
  1352. InstanceInitializer,
  1353. Interface,
  1354. Local,
  1355. Method,
  1356. Module,
  1357. ModuleReference,
  1358. OptionalModifier,
  1359. Parameter,
  1360. Pointer,
  1361. Property,
  1362. Reference,
  1363. RequiredModifier,
  1364. SecurityAttribute,
  1365. StaticInitializer,
  1366. Struct,
  1367. TypeParameter,
  1368. #if !MinimalReader
  1369. // The following NodeType definitions are not required
  1370. // for examining assembly metadata directly from binaries
  1371. //Serialization tags used for values that are not leaf nodes.
  1372. Array,
  1373. BlockReference,
  1374. CompilationParameters,
  1375. Document,
  1376. EndOfRecord,
  1377. Expression,
  1378. Guid,
  1379. List,
  1380. MarshallingInformation,
  1381. Member,
  1382. MemberReference,
  1383. MissingBlockReference,
  1384. MissingExpression,
  1385. MissingMemberReference,
  1386. String,
  1387. StringDictionary,
  1388. TypeNode,
  1389. Uri,
  1390. XmlNode,
  1391. //Source-based AST node tags
  1392. AddEventHandler,
  1393. AliasDefinition,
  1394. AnonymousNestedFunction,
  1395. ApplyToAll,
  1396. ArglistArgumentExpression,
  1397. ArglistExpression,
  1398. ArrayTypeExpression,
  1399. As,
  1400. Assertion,
  1401. AssignmentExpression,
  1402. Assumption,
  1403. Base,
  1404. #endif
  1405. #if FxCop
  1406. BlockExpression,
  1407. StackVariable,
  1408. #endif
  1409. #if !MinimalReader
  1410. BlockExpression,
  1411. BoxedTypeExpression,
  1412. ClassExpression,
  1413. CoerceTuple,
  1414. CollectionEnumerator,
  1415. Comma,
  1416. Compilation,
  1417. CompilationUnit,
  1418. CompilationUnitSnippet,
  1419. Conditional,
  1420. ConstructDelegate,
  1421. ConstructFlexArray,
  1422. ConstructIterator,
  1423. ConstructTuple,
  1424. Continue,
  1425. CopyReference,
  1426. CurrentClosure,
  1427. Decrement,
  1428. DefaultValue,
  1429. DoWhile,
  1430. Exit,
  1431. ExplicitCoercion,
  1432. ExpressionSnippet,
  1433. FieldInitializerBlock,
  1434. Fixed,
  1435. FlexArrayTypeExpression,
  1436. For,
  1437. ForEach,
  1438. FunctionDeclaration,
  1439. FunctionTypeExpression,
  1440. Goto,
  1441. GotoCase,
  1442. If,
  1443. ImplicitThis,
  1444. Increment,
  1445. InvariantTypeExpression,
  1446. Is,
  1447. LabeledStatement,
  1448. LocalDeclaration,
  1449. LocalDeclarationsStatement,
  1450. Lock,
  1451. LogicalAnd,
  1452. LogicalOr,
  1453. LRExpression,
  1454. MethodCall,
  1455. NameBinding,
  1456. NonEmptyStreamTypeExpression,
  1457. NonNullableTypeExpression,
  1458. NonNullTypeExpression,
  1459. NullableTypeExpression,
  1460. NullCoalescingExpression,
  1461. OutAddress,
  1462. Parentheses,
  1463. PointerTypeExpression,
  1464. PostfixExpression,
  1465. PrefixExpression,
  1466. QualifiedIdentifer,
  1467. RefAddress,
  1468. ReferenceTypeExpression,
  1469. RefTypeExpression,
  1470. RefValueExpression,
  1471. RemoveEventHandler,
  1472. Repeat,
  1473. ResourceUse,
  1474. SetterValue,
  1475. StackAlloc,
  1476. StatementSnippet,
  1477. StreamTypeExpression,
  1478. Switch,
  1479. SwitchCase,
  1480. SwitchCaseBottom,
  1481. TemplateInstance,
  1482. TupleTypeExpression,
  1483. TypeExpression,
  1484. TypeIntersectionExpression,
  1485. TypeMemberSnippet,
  1486. Typeof,
  1487. TypeReference,
  1488. Typeswitch,
  1489. TypeswitchCase,
  1490. TypeUnionExpression,
  1491. UnaryPlus,
  1492. UsedNamespace,
  1493. VariableDeclaration,
  1494. While,
  1495. Yield,
  1496. //Extended metadata node tags
  1497. ConstrainedType,
  1498. TupleType,
  1499. TypeAlias,
  1500. TypeIntersection,
  1501. TypeUnion,
  1502. //Query node tags
  1503. Composition,
  1504. QueryAggregate,
  1505. QueryAlias,
  1506. QueryAll,
  1507. QueryAny,
  1508. QueryAxis,
  1509. QueryCommit,
  1510. QueryContext,
  1511. QueryDelete,
  1512. QueryDifference,
  1513. QueryDistinct,
  1514. QueryExists,
  1515. QueryFilter,
  1516. QueryGeneratedType,
  1517. QueryGroupBy,
  1518. QueryInsert,
  1519. QueryIntersection,
  1520. QueryIterator,
  1521. QueryJoin,
  1522. QueryLimit,
  1523. QueryOrderBy,
  1524. QueryOrderItem,
  1525. QueryPosition,
  1526. QueryProject,
  1527. QueryQuantifiedExpression,
  1528. QueryRollback,
  1529. QuerySelect,
  1530. QuerySingleton,
  1531. QueryTransact,
  1532. QueryTypeFilter,
  1533. QueryUnion,
  1534. QueryUpdate,
  1535. QueryYielder,
  1536. //Contract node tags
  1537. Acquire,
  1538. Comprehension,
  1539. ComprehensionBinding,
  1540. Ensures,
  1541. EnsuresExceptional,
  1542. EnsuresNormal,
  1543. Iff,
  1544. Implies,
  1545. Invariant,
  1546. LogicalEqual,
  1547. LogicalImply,
  1548. Maplet,
  1549. MethodContract,
  1550. Modelfield,
  1551. ModelfieldContract,
  1552. OldExpression,
  1553. Range,
  1554. Read,
  1555. Requires,
  1556. RequiresOtherwise,
  1557. RequiresPlain,
  1558. ReturnValue,
  1559. TypeContract,
  1560. Write,
  1561. //Node tags for explicit modifiers in front-end
  1562. OptionalModifierTypeExpression,
  1563. RequiredModifierTypeExpression,
  1564. //Temporary node tags
  1565. Count,
  1566. Exists,
  1567. ExistsUnique,
  1568. Forall,
  1569. Max,
  1570. Min,
  1571. Product,
  1572. Sum,
  1573. Quantifier,
  1574. #endif // MinimalReader
  1575. }
  1576. [Flags]
  1577. public enum AssemblyFlags{
  1578. None = 0x0000,
  1579. PublicKey = 0x0001,
  1580. Library = 0x0002,
  1581. Platform = 0x0004,
  1582. NowPlatform = 0x0006,
  1583. SideBySideCompatible = 0x0000,
  1584. NonSideBySideCompatible = 0x0010,
  1585. NonSideBySideProcess = 0x0020,
  1586. NonSideBySideMachine = 0x0030,
  1587. CompatibilityMask = 0x00F0,
  1588. Retargetable = 0x0100,
  1589. DisableJITcompileOptimizer = 0x4000,
  1590. EnableJITcompileTracking = 0x8000
  1591. }
  1592. public enum AssemblyHashAlgorithm{
  1593. None = 0x0000,
  1594. MD5 = 0x8003,
  1595. SHA1 = 0x8004
  1596. }
  1597. [Flags]
  1598. public enum CallingConventionFlags{
  1599. Default = 0x0,
  1600. C = 0x1,
  1601. StandardCall = 0x2,
  1602. ThisCall = 0x3,
  1603. FastCall = 0x4,
  1604. VarArg = 0x5,
  1605. ArgumentConvention = 0x7,
  1606. Generic = 0x10,
  1607. HasThis = 0x20,
  1608. ExplicitThis = 0x40
  1609. }
  1610. [Flags]
  1611. public enum EventFlags{
  1612. None = 0x0000,
  1613. SpecialName = 0x0200,
  1614. ReservedMask = 0x0400,
  1615. RTSpecialName = 0x0400,
  1616. #if !MinimalReader
  1617. Extend = MethodFlags.Extend, // used for languages with type extensions, e.g. Sing#
  1618. #endif
  1619. }
  1620. [Flags]
  1621. public enum FieldFlags{
  1622. None = 0x0000,
  1623. FieldAccessMask = 0x0007,
  1624. CompilerControlled = 0x0000,
  1625. Private = 0x0001,
  1626. FamANDAssem = 0x0002,
  1627. Assembly = 0x0003,
  1628. Family = 0x0004,
  1629. FamORAssem = 0x0005,
  1630. Public = 0x0006,
  1631. Static = 0x0010,
  1632. InitOnly = 0x0020,
  1633. Literal = 0x0040,
  1634. NotSerialized = 0x0080,
  1635. SpecialName = 0x0200,
  1636. PinvokeImpl = 0x2000,
  1637. ReservedMask = 0x9500,
  1638. RTSpecialName = 0x0400,
  1639. HasFieldMarshal = 0x1000,
  1640. HasDefault = 0x8000,
  1641. HasFieldRVA = 0x0100,
  1642. }
  1643. [Flags]
  1644. public enum FileFlags{
  1645. ContainsMetaData = 0x0000,
  1646. ContainsNoMetaData = 0x0001
  1647. }
  1648. [Flags]
  1649. public enum TypeParameterFlags{
  1650. NonVariant = 0x0000,
  1651. Covariant = 0x0001,
  1652. Contravariant = 0x0002,
  1653. VarianceMask = 0x0003,
  1654. NoSpecialConstraint = 0x0000,
  1655. ReferenceTypeConstraint = 0x0004,
  1656. ValueTypeConstraint = 0x0008,
  1657. DefaultConstructorConstraint = 0x0010,
  1658. SpecialConstraintMask = 0x001C,
  1659. }
  1660. [Flags]
  1661. public enum MethodImplFlags{
  1662. CodeTypeMask = 0x0003,
  1663. IL = 0x0000,
  1664. Native = 0x0001,
  1665. OPTIL = 0x0002,
  1666. Runtime = 0x0003,
  1667. ManagedMask = 0x0004,
  1668. Unmanaged = 0x0004,
  1669. Managed = 0x0000,
  1670. ForwardRef = 0x0010,
  1671. PreserveSig = 0x0080,
  1672. InternalCall = 0x1000,
  1673. Synchronized = 0x0020,
  1674. NoInlining = 0x0008,
  1675. #if !MinimalReader
  1676. MaxMethodImplVal = 0xffff
  1677. #endif
  1678. }
  1679. [Flags]
  1680. public enum MethodFlags{
  1681. MethodAccessMask = 0x0007,
  1682. CompilerControlled = 0x0000,
  1683. Private = 0x0001,
  1684. FamANDAssem = 0x0002,
  1685. Assembly = 0x0003,
  1686. Family = 0x0004,
  1687. FamORAssem = 0x0005,
  1688. Public = 0x0006,
  1689. Static = 0x0010,
  1690. Final = 0x0020,
  1691. Virtual = 0x0040,
  1692. HideBySig = 0x0080,
  1693. VtableLayoutMask = 0x0100,
  1694. ReuseSlot = 0x0000,
  1695. NewSlot = 0x0100,
  1696. CheckAccessOnOverride = 0x0200,
  1697. Abstract = 0x0400,
  1698. SpecialName = 0x0800,
  1699. PInvokeImpl = 0x2000,
  1700. UnmanagedExport = 0xd000,
  1701. ReservedMask = 0xd000,
  1702. RTSpecialName = 0x1000,
  1703. HasSecurity = 0x4000,
  1704. RequireSecObject = 0x8000,
  1705. #if !MinimalReader
  1706. Extend = 0x01000000, // used for languages with type extensions, e.g. Sing#
  1707. #endif
  1708. }
  1709. public enum ModuleKindFlags{ //TODO: rename this to just ModuleKind
  1710. ConsoleApplication,
  1711. WindowsApplication,
  1712. DynamicallyLinkedLibrary,
  1713. ManifestResourceFile,
  1714. UnmanagedDynamicallyLinkedLibrary
  1715. }
  1716. [Flags]
  1717. public enum ParameterFlags{
  1718. None = 0x0000,
  1719. In = 0x0001,
  1720. Out = 0x0002,
  1721. Optional = 0x0010,
  1722. ReservedMask = 0xf000,
  1723. HasDefault = 0x1000,
  1724. HasFieldMarshal = 0x2000
  1725. }
  1726. [Flags]
  1727. public enum PEKindFlags{
  1728. ILonly = 0x0001,
  1729. Requires32bits = 0x0002,
  1730. Requires64bits = 0x0004,
  1731. AMD = 0x0008
  1732. }
  1733. [Flags]
  1734. public enum PInvokeFlags{
  1735. None = 0x0000,
  1736. NoMangle = 0x0001,
  1737. BestFitDisabled = 0x0020,
  1738. BestFitEnabled = 0x0010,
  1739. BestFitUseAsm = 0x0000,
  1740. BestFitMask = 0x0030,
  1741. CharSetMask = 0x0006,
  1742. CharSetNotSpec = 0x0000,
  1743. CharSetAns = 0x0002,
  1744. CharSetUnicode = 0x0004,
  1745. CharSetAuto = 0x0006,
  1746. SupportsLastError = 0x0040,
  1747. CallingConvMask = 0x0700,
  1748. CallConvWinapi = 0x0100,
  1749. CallConvCdecl = 0x0200,
  1750. CallConvStdcall = 0x0300,
  1751. CallConvThiscall = 0x0400,
  1752. CallConvFastcall = 0x0500,
  1753. ThrowOnUnmappableCharMask = 0x3000,
  1754. ThrowOnUnmappableCharEnabled = 0x1000,
  1755. ThrowOnUnmappableCharDisabled = 0x2000,
  1756. ThrowOnUnmappableCharUseAsm = 0x0000
  1757. }
  1758. [Flags]
  1759. public enum PropertyFlags{
  1760. None = 0x0000,
  1761. SpecialName = 0x0200,
  1762. ReservedMask = 0xf400,
  1763. RTSpecialName = 0x0400,
  1764. #if !MinimalReader
  1765. Extend = MethodFlags.Extend, // used for languages with type extensions, e.g. Sing#
  1766. #endif
  1767. }
  1768. public enum PESection{
  1769. Text,
  1770. SData,
  1771. TLS
  1772. };
  1773. #if !MinimalReader
  1774. public enum ProcessorType{
  1775. Any,
  1776. x86,
  1777. x64,
  1778. Itanium,
  1779. }
  1780. #endif
  1781. [Flags]
  1782. public enum TypeFlags{
  1783. None = 0x00000000,
  1784. VisibilityMask = 0x00000007,
  1785. NotPublic = 0x00000000,
  1786. Public = 0x00000001,
  1787. NestedPublic = 0x00000002,
  1788. NestedPrivate = 0x00000003,
  1789. NestedFamily = 0x00000004,
  1790. NestedAssembly = 0x00000005,
  1791. NestedFamANDAssem = 0x00000006,
  1792. NestedFamORAssem = 0x00000007,
  1793. LayoutMask = 0x00000018,
  1794. AutoLayout = 0x00000000,
  1795. SequentialLayout = 0x00000008,
  1796. ExplicitLayout = 0x00000010,
  1797. ClassSemanticsMask= 0x00000020,
  1798. Class = 0x00000000,
  1799. Interface = 0x00000020,
  1800. LayoutOverridden = 0x00000040, // even AutoLayout can be explicit or implicit
  1801. Abstract = 0x00000080,
  1802. Sealed = 0x00000100,
  1803. SpecialName = 0x00000400,
  1804. Import = 0x00001000,
  1805. Serializable = 0x00002000,
  1806. StringFormatMask = 0x00030000,
  1807. AnsiClass = 0x00000000,
  1808. UnicodeClass = 0x00010000,
  1809. AutoClass = 0x00020000,
  1810. BeforeFieldInit = 0x00100000,
  1811. ReservedMask = 0x00040800,
  1812. RTSpecialName = 0x00000800,
  1813. HasSecurity = 0x00040000,
  1814. Forwarder = 0x00200000, //The type is a stub left behind for backwards compatibility. References to this type are forwarded to another type by the CLR.
  1815. #if !MinimalReader
  1816. Extend = 0x01000000, // used for languages with type extensions, e.g. Sing#
  1817. #endif
  1818. }
  1819. public sealed class TrivialHashtable{
  1820. struct HashEntry {
  1821. public int Key;
  1822. public object Value;
  1823. }
  1824. private HashEntry[]/*!*/ entries;
  1825. private int count;
  1826. public TrivialHashtable(){
  1827. this.entries = new HashEntry[16];
  1828. //this.count = 0;
  1829. }
  1830. private TrivialHashtable(HashEntry[]/*!*/ entries, int count) {
  1831. this.entries = entries;
  1832. this.count = count;
  1833. }
  1834. public TrivialHashtable(int expectedEntries) {
  1835. int initialSize = 16;
  1836. expectedEntries <<= 1;
  1837. while (initialSize < expectedEntries && initialSize > 0) initialSize <<= 1;
  1838. if (initialSize < 0) initialSize = 16;
  1839. this.entries = new HashEntry[initialSize];
  1840. //this.count = 0;
  1841. }
  1842. public int Count{
  1843. get{
  1844. return this.count;
  1845. }
  1846. }
  1847. private void Expand(){
  1848. HashEntry[] oldEntries = this.entries;
  1849. int n = oldEntries.Length;
  1850. int m = n*2;
  1851. if (m <= 0) return;
  1852. HashEntry[] entries = new HashEntry[m];
  1853. int count = 0;
  1854. for (int i = 0; i < n; i++){
  1855. int key = oldEntries[i].Key;
  1856. if (key <= 0) continue; //No entry (0) or deleted entry (-1)
  1857. object value = oldEntries[i].Value;
  1858. Debug.Assert(value != null);
  1859. int j = key & (m-1);
  1860. int k = entries[j].Key;
  1861. while (true){
  1862. if (k == 0){
  1863. entries[j].Value = value;
  1864. entries[j].Key = key;
  1865. count++;
  1866. break;
  1867. }
  1868. j++; if (j >= m) j = 0;
  1869. k = entries[j].Key;
  1870. }
  1871. }
  1872. this.entries = entries;
  1873. this.count = count;
  1874. }
  1875. public object this[int key]{
  1876. get{
  1877. if (key <= 0) throw new ArgumentException(ExceptionStrings.KeyNeedsToBeGreaterThanZero, "key");
  1878. HashEntry[] entries = this.entries;
  1879. int n = entries.Length;
  1880. int i = key & (n-1);
  1881. int k = entries[i].Key;
  1882. object result = null;
  1883. while (true){
  1884. if (k == key){result = entries[i].Value; break;}
  1885. if (k == 0) break;
  1886. i++; if (i >= n) i = 0;
  1887. k = entries[i].Key;
  1888. }
  1889. return result;
  1890. }
  1891. set{
  1892. if (key <= 0) throw new ArgumentException(ExceptionStrings.KeyNeedsToBeGreaterThanZero, "key");
  1893. HashEntry[] entries = this.entries;
  1894. int n = entries.Length;
  1895. int i = key & (n-1);
  1896. int k = entries[i].Key;
  1897. while(true){
  1898. if (k == key || k == 0){
  1899. entries[i].Value = value;
  1900. if (k == 0){
  1901. if (value == null){return;}
  1902. entries[i].Key = key;
  1903. if (++this.count > n/2) this.Expand();
  1904. return;
  1905. }
  1906. if (value == null) entries[i].Key = -1;
  1907. return;
  1908. }
  1909. i++; if (i >= n) i = 0;
  1910. k = entries[i].Key;
  1911. }
  1912. }
  1913. }
  1914. public TrivialHashtable Clone(){
  1915. HashEntry[] clonedEntries = (HashEntry[]) this.entries.Clone();
  1916. //^ assume clonedEntries != null;
  1917. return new TrivialHashtable(clonedEntries, this.count);
  1918. }
  1919. }
  1920. #if !FxCop
  1921. public
  1922. #endif
  1923. sealed class TrivialHashtableUsingWeakReferences{
  1924. struct HashEntry {
  1925. public int Key;
  1926. public WeakReference Value;
  1927. }
  1928. private HashEntry[]/*!*/ entries;
  1929. private int count;
  1930. public TrivialHashtableUsingWeakReferences(){
  1931. this.entries = new HashEntry[16];
  1932. //this.count = 0;
  1933. }
  1934. private TrivialHashtableUsingWeakReferences(HashEntry[]/*!*/ entries, int count) {
  1935. this.entries = entries;
  1936. this.count = count;
  1937. }
  1938. public TrivialHashtableUsingWeakReferences(int expectedEntries) {
  1939. int initialSize = 16;
  1940. expectedEntries <<= 1;
  1941. while (initialSize < expectedEntries && initialSize > 0) initialSize <<= 1;
  1942. if (initialSize < 0) initialSize = 16;
  1943. this.entries = new HashEntry[initialSize];
  1944. //this.count = 0;
  1945. }
  1946. public int Count{
  1947. get{
  1948. return this.count;
  1949. }
  1950. }
  1951. private void Expand(){
  1952. HashEntry[] oldEntries = this.entries;
  1953. int n = oldEntries.Length;
  1954. int m = n*2;
  1955. if (m <= 0) return;
  1956. HashEntry[] entries = new HashEntry[m];
  1957. int count = 0;
  1958. for (int i = 0; i < n; i++){
  1959. int key = oldEntries[i].Key;
  1960. if (key <= 0) continue; //No entry (0) or deleted entry (-1)
  1961. WeakReference value = oldEntries[i].Value;
  1962. Debug.Assert(value != null);
  1963. if (value == null || !value.IsAlive) continue; //Collected entry.
  1964. int j = key & (m-1);
  1965. int k = entries[j].Key;
  1966. while (true){
  1967. if (k == 0){
  1968. entries[j].Value = value;
  1969. entries[j].Key = key;
  1970. count++;
  1971. break;
  1972. }
  1973. j++; if (j >= m) j = 0;
  1974. k = entries[j].Key;
  1975. }
  1976. }
  1977. this.entries = entries;
  1978. this.count = count;
  1979. }
  1980. private void Contract() {
  1981. HashEntry[] oldEntries = this.entries;
  1982. int n = oldEntries.Length;
  1983. int m = n/2;
  1984. if (m < 16) return;
  1985. HashEntry[] entries = new HashEntry[m];
  1986. int count = 0;
  1987. for (int i = 0; i < n; i++) {
  1988. int key = oldEntries[i].Key;
  1989. if (key <= 0) continue; //No entry (0) or deleted entry (-1)
  1990. WeakReference value = oldEntries[i].Value;
  1991. Debug.Assert(value != null);
  1992. if (value == null || !value.IsAlive) continue; //Collected entry.
  1993. int j = key & (m-1);
  1994. int k = entries[j].Key;
  1995. while (true) {
  1996. if (k == 0) {
  1997. entries[j].Value = value;
  1998. entries[j].Key = key;
  1999. count++;
  2000. break;
  2001. }
  2002. j++; if (j >= m) j = 0;
  2003. k = entries[j].Key;
  2004. }
  2005. }
  2006. this.entries = entries;
  2007. this.count = count;
  2008. }
  2009. private void WeedOutCollectedEntries() {
  2010. HashEntry[] oldEntries = this.entries;
  2011. int n = oldEntries.Length;
  2012. HashEntry[] entries = new HashEntry[n];
  2013. int count = 0;
  2014. for (int i = 0; i < n; i++) {
  2015. int key = oldEntries[i].Key;
  2016. if (key <= 0) continue; //No entry (0) or deleted entry (-1)
  2017. WeakReference value = oldEntries[i].Value;
  2018. Debug.Assert(value != null);
  2019. if (value == null || !value.IsAlive) continue; //Collected entry.
  2020. int j = key & (n-1);
  2021. int k = entries[j].Key;
  2022. while (true) {
  2023. if (k == 0) {
  2024. entries[j].Value = value;
  2025. entries[j].Key = key;
  2026. count++;
  2027. break;
  2028. }
  2029. j++; if (j >= n) j = 0;
  2030. k = entries[j].Key;
  2031. }
  2032. }
  2033. this.entries = entries;
  2034. this.count = count;
  2035. }
  2036. public object this[int key] {
  2037. get{
  2038. if (key <= 0) throw new ArgumentException(ExceptionStrings.KeyNeedsToBeGreaterThanZero, "key");
  2039. HashEntry[] entries = this.entries;
  2040. int n = entries.Length;
  2041. int i = key & (n-1);
  2042. int k = entries[i].Key;
  2043. object result = null;
  2044. while (true){
  2045. if (k == key){
  2046. WeakReference wref = entries[i].Value;
  2047. if (wref == null) { Debug.Assert(false); return null; }
  2048. result = wref.Target;
  2049. if (result != null) return result;
  2050. this.WeedOutCollectedEntries();
  2051. while (this.count < n/4 && n > 16) { this.Contract(); n = this.entries.Length; }
  2052. return null;
  2053. }
  2054. if (k == 0) break;
  2055. i++; if (i >= n) i = 0;
  2056. k = entries[i].Key;
  2057. }
  2058. return result;
  2059. }
  2060. set{
  2061. if (key <= 0) throw new ArgumentException(ExceptionStrings.KeyNeedsToBeGreaterThanZero, "key");
  2062. HashEntry[] entries = this.entries;
  2063. int n = entries.Length;
  2064. int i = key & (n-1);
  2065. int k = entries[i].Key;
  2066. while(true){
  2067. if (k == key || k == 0) {
  2068. if (value == null)
  2069. entries[i].Value = null;
  2070. else
  2071. entries[i].Value = new WeakReference(value);
  2072. if (k == 0) {
  2073. if (value == null) return;
  2074. entries[i].Key = key;
  2075. if (++this.count > n/2) {
  2076. this.Expand(); //Could decrease this.count because of collected entries being deleted
  2077. while (this.count < n/4 && n > 16) { this.Contract(); n = this.entries.Length; }
  2078. }
  2079. return;
  2080. }
  2081. if (value == null) entries[i].Key = -1;
  2082. return;
  2083. }
  2084. i++; if (i >= n) i = 0;
  2085. k = entries[i].Key;
  2086. }
  2087. }
  2088. }
  2089. public TrivialHashtableUsingWeakReferences Clone() {
  2090. HashEntry[] clonedEntries = (HashEntry[]) this.entries.Clone();
  2091. //^ assume clonedEntries != null;
  2092. return new TrivialHashtableUsingWeakReferences(clonedEntries, this.count);
  2093. }
  2094. }
  2095. public interface IUniqueKey{
  2096. int UniqueId{get;}
  2097. }
  2098. /// <summary>
  2099. /// A node in an Abstract Syntax Tree.
  2100. /// </summary>
  2101. public abstract class Node : IUniqueKey{
  2102. #if !MinimalReader
  2103. public bool IsErroneous;
  2104. #endif
  2105. /// <summary>
  2106. /// The region in the source code that contains the concrete syntax corresponding to this node in the Abstract Syntax Tree.
  2107. /// </summary>
  2108. #if !FxCop
  2109. public SourceContext SourceContext;
  2110. #else
  2111. internal SourceContext sourceContext;
  2112. public SourceContext SourceContext {
  2113. get{return this.sourceContext;}
  2114. internal set{this.sourceContext = value;}
  2115. }
  2116. #endif
  2117. #if DEBUG && !MinimalReader
  2118. public string DebugLabel; // useful for debugging.
  2119. #endif
  2120. protected Node(NodeType nodeType){
  2121. this.NodeType = nodeType;
  2122. }
  2123. private NodeType nodeType;
  2124. /// <summary>
  2125. /// A scalar tag that identifies the concrete type of the node. This is provided to allow efficient type membership tests that
  2126. /// facilitate tree traversal.
  2127. /// </summary>
  2128. public NodeType NodeType{
  2129. get{return this.nodeType;}
  2130. set{this.nodeType = value;}
  2131. }
  2132. private static int uniqueKeyCounter;
  2133. private int uniqueKey;
  2134. /// <summary>
  2135. /// An integer that uniquely identifies this node. This provides an efficient equality test to facilitate hashing.
  2136. /// Do not override this.
  2137. /// </summary>
  2138. public virtual int UniqueKey{
  2139. get{
  2140. if (this.uniqueKey == 0){
  2141. TryAgain:
  2142. int c = Node.uniqueKeyCounter;
  2143. int cp1 = c+17;
  2144. if (cp1 <= 0) cp1 = 1000000;
  2145. if (System.Threading.Interlocked.CompareExchange(ref Node.uniqueKeyCounter, cp1, c) != c) goto TryAgain;
  2146. this.uniqueKey = cp1;
  2147. }
  2148. return this.uniqueKey;
  2149. }
  2150. }
  2151. /// <summary>
  2152. /// Makes a shallow copy of the node.
  2153. /// </summary>
  2154. /// <returns>A shallow copy of the node</returns>
  2155. public virtual Node/*!*/ Clone() {
  2156. Node result = (Node)this.MemberwiseClone();
  2157. result.uniqueKey = 0;
  2158. return result;
  2159. }
  2160. #if !MinimalReader
  2161. public virtual object GetVisitorFor(object/*!*/ callingVisitor, string/*!*/ visitorClassName) {
  2162. if (callingVisitor == null || visitorClassName == null) { Debug.Fail(""); return null; }
  2163. return Node.GetVisitorFor(this.GetType(), callingVisitor, visitorClassName);
  2164. }
  2165. private static Hashtable VisitorTypeFor; //contains weak references
  2166. private static Object GetVisitorFor(System.Type/*!*/ nodeType, object/*!*/ callingVisitor, string/*!*/ visitorClassName) {
  2167. if (nodeType == null || callingVisitor == null || visitorClassName == null){Debug.Fail(""); return null;}
  2168. if (Node.VisitorTypeFor == null) Node.VisitorTypeFor = new Hashtable();
  2169. string customVisitorClassName = visitorClassName;
  2170. if (visitorClassName.IndexOf('.') < 0) customVisitorClassName = nodeType.Namespace + "." + visitorClassName;
  2171. if (customVisitorClassName == callingVisitor.GetType().FullName){
  2172. Debug.Assert(false); //This must be a bug, the calling visitor is the one that should handle the nodeType
  2173. return null;
  2174. }
  2175. System.Reflection.AssemblyName visitorAssemblyName = null;
  2176. System.Reflection.Assembly assembly = null;
  2177. WeakReference wref = (WeakReference)Node.VisitorTypeFor[customVisitorClassName];
  2178. Type visitorType = wref == null ? null : (System.Type)wref.Target;
  2179. if (visitorType == typeof(object)) return null;
  2180. string callerDirectory = null;
  2181. if (visitorType == null){
  2182. assembly = nodeType.Assembly;
  2183. if (assembly == null) return null;
  2184. visitorType = assembly.GetType(customVisitorClassName, false);
  2185. }
  2186. if (visitorType == null) {
  2187. //^ assert assembly != null;
  2188. if (assembly.Location == null) return null;
  2189. callerDirectory = Path.GetDirectoryName(assembly.Location);
  2190. visitorAssemblyName = new System.Reflection.AssemblyName();
  2191. visitorAssemblyName.Name = "Visitors";
  2192. visitorAssemblyName.CodeBase = "file:///" + Path.Combine(callerDirectory, "Visitors.dll");
  2193. try {
  2194. assembly = System.Reflection.Assembly.Load(visitorAssemblyName);
  2195. } catch { }
  2196. if (assembly != null)
  2197. visitorType = assembly.GetType(customVisitorClassName, false);
  2198. if (visitorType == null) {
  2199. visitorAssemblyName.Name = customVisitorClassName;
  2200. visitorAssemblyName.CodeBase = "file:///" + Path.Combine(callerDirectory, customVisitorClassName+".dll");
  2201. try {
  2202. assembly = System.Reflection.Assembly.Load(visitorAssemblyName);
  2203. } catch { }
  2204. if (assembly != null)
  2205. visitorType = assembly.GetType(customVisitorClassName, false);
  2206. }
  2207. }
  2208. if (visitorType == null){
  2209. //Put fake entry into hashtable to short circuit future lookups
  2210. visitorType = typeof(object);
  2211. assembly = nodeType.Assembly;
  2212. }
  2213. if (assembly != null){ //Only happens if there was a cache miss
  2214. lock(Node.VisitorTypeFor){
  2215. Node.VisitorTypeFor[customVisitorClassName] = new WeakReference(visitorType);
  2216. }
  2217. }
  2218. if (visitorType == typeof(object)) return null;
  2219. try{
  2220. return System.Activator.CreateInstance(visitorType, new object[]{callingVisitor});
  2221. }catch{}
  2222. return null;
  2223. }
  2224. #endif
  2225. int IUniqueKey.UniqueId { get { return this.UniqueKey; } }
  2226. #if MinimalReader
  2227. // Return a constant value for IsNormalized in the binary-only
  2228. // reader. This results in less code churn elsewhere.
  2229. internal bool IsNormalized{get{return true;}}
  2230. #endif
  2231. }
  2232. #if !MinimalReader
  2233. public abstract class ErrorNode : Node{
  2234. public int Code;
  2235. #if ExtendedRuntime
  2236. public bool DoNotSuppress;
  2237. #endif
  2238. public string[] MessageParameters;
  2239. protected ErrorNode(int code, params string[] messageParameters)
  2240. : base(NodeType.Undefined){
  2241. this.Code = code;
  2242. this.MessageParameters = messageParameters;
  2243. }
  2244. public virtual string GetErrorNumber(){
  2245. return this.Code.ToString("0000");
  2246. }
  2247. public string GetMessage(){
  2248. return this.GetMessage(null);
  2249. }
  2250. #if ExtendedRuntime
  2251. [return: Microsoft.Contracts.NotNull]
  2252. #endif
  2253. public abstract string GetMessage(System.Globalization.CultureInfo culture);
  2254. public virtual string GetMessage(string key, System.Resources.ResourceManager rm, System.Globalization.CultureInfo culture){
  2255. if (rm == null || key == null) return null;
  2256. string localizedString = rm.GetString(key, culture);
  2257. if (localizedString == null) localizedString = key;
  2258. string[] messageParameters = this.MessageParameters;
  2259. if (messageParameters == null || messageParameters.Length == 0) return localizedString;
  2260. return string.Format(localizedString, messageParameters);
  2261. }
  2262. public abstract int Severity{
  2263. get;
  2264. }
  2265. public static int GetCountAtSeverity(ErrorNodeList errors, int minSeverity, int maxSeverity){
  2266. if (errors == null) return 0;
  2267. int n = 0;
  2268. for (int i = 0; i < errors.Count; i++){
  2269. ErrorNode e = errors[i];
  2270. if (e == null)
  2271. continue;
  2272. int s = e.Severity;
  2273. if (minSeverity <= s && s <= maxSeverity)
  2274. n++;
  2275. }
  2276. return n;
  2277. }
  2278. }
  2279. public class Expose : Statement{
  2280. public Expression Instance;
  2281. public Block Body;
  2282. public bool IsLocal;
  2283. public Expose(NodeType nodeType)
  2284. : base(nodeType){
  2285. }
  2286. }
  2287. public class Acquire : Statement{
  2288. public bool ReadOnly;
  2289. public Statement Target;
  2290. public Expression Condition;
  2291. public Expression ConditionFunction;
  2292. public Block Body;
  2293. public BlockScope ScopeForTemporaryVariable;
  2294. public Acquire() : base(NodeType.Acquire) {
  2295. }
  2296. }
  2297. #endif
  2298. public class Expression : Node{
  2299. private TypeNode type;
  2300. #if FxCop
  2301. internal int ILOffset;
  2302. #endif
  2303. #if !FxCop && ILOFFSETS
  2304. public int ILOffset;
  2305. #endif
  2306. public Expression(NodeType nodeType)
  2307. : base(nodeType){
  2308. }
  2309. public Expression(NodeType nodeType, TypeNode type)
  2310. : base(nodeType){
  2311. this.type = type;
  2312. }
  2313. public virtual TypeNode Type{
  2314. get{return this.type;}
  2315. set{this.type = value;}
  2316. }
  2317. }
  2318. #if !MinimalReader
  2319. public class ExpressionSnippet : Expression{
  2320. public IParserFactory ParserFactory;
  2321. public ExpressionSnippet()
  2322. : base(NodeType.ExpressionSnippet){
  2323. }
  2324. public ExpressionSnippet(IParserFactory parserFactory, SourceContext sctx)
  2325. : base(NodeType.ExpressionSnippet){
  2326. this.ParserFactory = parserFactory;
  2327. this.SourceContext = sctx;
  2328. }
  2329. }
  2330. #endif
  2331. public class MemberBinding : Expression{
  2332. private int alignment;
  2333. private Member boundMember;
  2334. #if !MinimalReader
  2335. public Expression BoundMemberExpression;
  2336. #endif
  2337. private Expression targetObject;
  2338. private bool @volatile;
  2339. public MemberBinding()
  2340. : base(NodeType.MemberBinding){
  2341. }
  2342. public MemberBinding(Expression targetObject, Member/*!*/ boundMember)
  2343. : this(targetObject, boundMember, false, -1){
  2344. if (boundMember is Field) this.Volatile = ((Field)boundMember).IsVolatile;
  2345. }
  2346. #if !MinimalReader
  2347. public MemberBinding(Expression targetObject, Member/*!*/ boundMember, Expression boundMemberExpression)
  2348. : this(targetObject, boundMember, false, -1){
  2349. if (boundMember is Field) this.Volatile = ((Field)boundMember).IsVolatile;
  2350. this.BoundMemberExpression = boundMemberExpression;
  2351. }
  2352. public MemberBinding(Expression targetObject, Member/*!*/ boundMember, SourceContext sctx)
  2353. : this(targetObject, boundMember, false, -1){
  2354. if (boundMember is Field) this.Volatile = ((Field)boundMember).IsVolatile;
  2355. this.SourceContext = sctx;
  2356. }
  2357. public MemberBinding(Expression targetObject, Member/*!*/ boundMember, SourceContext sctx, Expression boundMemberExpression)
  2358. : this(targetObject, boundMember, false, -1){
  2359. if (boundMember is Field) this.Volatile = ((Field)boundMember).IsVolatile;
  2360. this.SourceContext = sctx;
  2361. this.BoundMemberExpression = boundMemberExpression;
  2362. }
  2363. #endif
  2364. public MemberBinding(Expression targetObject, Member/*!*/ boundMember, bool @volatile, int alignment)
  2365. : base(NodeType.MemberBinding){
  2366. Debug.Assert(boundMember != null);
  2367. this.alignment = alignment;
  2368. this.boundMember = boundMember;
  2369. this.targetObject = targetObject;
  2370. this.@volatile = @volatile;
  2371. switch(boundMember.NodeType){
  2372. case NodeType.Field : this.Type = ((Field)boundMember).Type; break;
  2373. case NodeType.Method : this.Type = ((Method)boundMember).ReturnType; break;
  2374. case NodeType.Event : this.Type = ((Event)boundMember).HandlerType; break;
  2375. default : this.Type = boundMember as TypeNode; break;
  2376. }
  2377. }
  2378. public int Alignment{
  2379. get{return this.alignment;}
  2380. set{this.alignment = value;}
  2381. }
  2382. public Member BoundMember{
  2383. get{return this.boundMember;}
  2384. set{this.boundMember = value;}
  2385. }
  2386. public Expression TargetObject{
  2387. get{return this.targetObject;}
  2388. set{this.targetObject = value;}
  2389. }
  2390. public bool Volatile{
  2391. get{return this.@volatile;}
  2392. set{this.@volatile = value;}
  2393. }
  2394. }
  2395. public class AddressDereference : Expression{
  2396. private Expression address;
  2397. private int alignment;
  2398. private bool isVolatile;
  2399. #if !MinimalReader
  2400. public enum ExplicitOp { None=0, Star, Arrow }
  2401. private ExplicitOp explicitOperation; // was explicit in source (* or ->)
  2402. #endif
  2403. public AddressDereference()
  2404. : base(NodeType.AddressDereference){
  2405. }
  2406. public AddressDereference(Expression address, TypeNode type)
  2407. : this(address, type, false, -1){
  2408. }
  2409. #if !MinimalReader
  2410. public AddressDereference(Expression address, TypeNode type, SourceContext sctx)
  2411. : this(address, type, false, -1, sctx){
  2412. }
  2413. #endif
  2414. public AddressDereference(Expression address, TypeNode type, bool isVolatile, int alignment)
  2415. : base(NodeType.AddressDereference){
  2416. this.address = address;
  2417. this.alignment = alignment;
  2418. this.Type = type;
  2419. this.isVolatile = isVolatile;
  2420. }
  2421. #if !MinimalReader
  2422. public AddressDereference(Expression address, TypeNode type, bool Volatile, int alignment, SourceContext sctx)
  2423. : base(NodeType.AddressDereference){
  2424. this.address = address;
  2425. this.alignment = alignment;
  2426. this.Type = type;
  2427. this.isVolatile = Volatile;
  2428. this.SourceContext = sctx;
  2429. }
  2430. #endif
  2431. public Expression Address{
  2432. get{return this.address;}
  2433. set{this.address = value;}
  2434. }
  2435. public int Alignment{
  2436. get{return this.alignment;}
  2437. set{this.alignment = value;}
  2438. }
  2439. public bool Volatile{
  2440. get{return this.isVolatile;}
  2441. set{this.isVolatile = value;}
  2442. }
  2443. #if !MinimalReader
  2444. public bool Explicit{
  2445. get{return this.explicitOperation != ExplicitOp.None;}
  2446. }
  2447. public ExplicitOp ExplicitOperator {
  2448. get { return this.explicitOperation; }
  2449. set { this.explicitOperation = value; }
  2450. }
  2451. #endif
  2452. }
  2453. public class UnaryExpression : Expression{
  2454. private Expression operand;
  2455. public UnaryExpression()
  2456. : base(NodeType.Nop){
  2457. }
  2458. public UnaryExpression(Expression operand, NodeType nodeType)
  2459. : base(nodeType){
  2460. this.Operand = operand;
  2461. }
  2462. #if !MinimalReader
  2463. public UnaryExpression(Expression operand, NodeType nodeType, SourceContext sctx)
  2464. : base(nodeType){
  2465. this.operand = operand;
  2466. this.SourceContext = sctx;
  2467. }
  2468. #endif
  2469. public UnaryExpression(Expression operand, NodeType nodeType, TypeNode type)
  2470. : base(nodeType){
  2471. this.operand = operand;
  2472. this.Type = type;
  2473. }
  2474. #if !MinimalReader
  2475. public UnaryExpression(Expression operand, NodeType nodeType, TypeNode type, SourceContext sctx)
  2476. : base(nodeType){
  2477. this.operand = operand;
  2478. this.Type = type;
  2479. this.SourceContext = sctx;
  2480. }
  2481. #endif
  2482. public Expression Operand{
  2483. get{return this.operand;}
  2484. set{this.operand = value;}
  2485. }
  2486. }
  2487. #if !MinimalReader
  2488. public class PrefixExpression : Expression{
  2489. public Expression Expression;
  2490. public NodeType Operator;
  2491. public Method OperatorOverload;
  2492. public PrefixExpression()
  2493. : base(NodeType.PrefixExpression){
  2494. }
  2495. public PrefixExpression(Expression expression, NodeType Operator, SourceContext sourceContext)
  2496. : base(NodeType.PrefixExpression){
  2497. this.Expression = expression;
  2498. this.Operator = Operator;
  2499. this.SourceContext = sourceContext;
  2500. }
  2501. }
  2502. public class PostfixExpression : Expression{
  2503. public Expression Expression;
  2504. public NodeType Operator;
  2505. public Method OperatorOverload;
  2506. public PostfixExpression()
  2507. : base(NodeType.PostfixExpression){
  2508. }
  2509. public PostfixExpression(Expression expression, NodeType Operator, SourceContext sourceContext)
  2510. : base(NodeType.PostfixExpression){
  2511. this.Expression = expression;
  2512. this.Operator = Operator;
  2513. this.SourceContext = sourceContext;
  2514. }
  2515. }
  2516. #endif
  2517. public class BinaryExpression : Expression{
  2518. private Expression operand1;
  2519. private Expression operand2;
  2520. public BinaryExpression()
  2521. : base(NodeType.Nop){
  2522. }
  2523. public BinaryExpression(Expression operand1, Expression operand2, NodeType nodeType)
  2524. : base(nodeType){
  2525. this.operand1 = operand1;
  2526. this.operand2 = operand2;
  2527. }
  2528. public BinaryExpression(Expression operand1, Expression operand2, NodeType nodeType, TypeNode resultType)
  2529. : base(nodeType){
  2530. this.operand1 = operand1;
  2531. this.operand2 = operand2;
  2532. this.Type = resultType;
  2533. }
  2534. #if !MinimalReader
  2535. public BinaryExpression(Expression operand1, Expression operand2, NodeType nodeType, SourceContext ctx)
  2536. : base(nodeType){
  2537. this.operand1 = operand1;
  2538. this.operand2 = operand2;
  2539. this.SourceContext = ctx;
  2540. }
  2541. public BinaryExpression(Expression operand1, Expression operand2, NodeType nodeType, TypeNode resultType, SourceContext ctx)
  2542. : base(nodeType){
  2543. this.operand1 = operand1;
  2544. this.operand2 = operand2;
  2545. this.Type = resultType;
  2546. this.SourceContext = ctx;
  2547. }
  2548. #endif
  2549. public Expression Operand1{
  2550. get{return this.operand1;}
  2551. set{this.operand1 = value;}
  2552. }
  2553. public Expression Operand2{
  2554. get{return this.operand2;}
  2555. set{this.operand2 = value;}
  2556. }
  2557. }
  2558. public class TernaryExpression : Expression{
  2559. private Expression operand1;
  2560. private Expression operand2;
  2561. private Expression operand3;
  2562. public TernaryExpression()
  2563. : base(NodeType.Nop){
  2564. }
  2565. public TernaryExpression(Expression operand1, Expression operand2, Expression operand3, NodeType nodeType, TypeNode resultType)
  2566. : base(nodeType){
  2567. this.operand1 = operand1;
  2568. this.operand2 = operand2;
  2569. this.operand3 = operand3;
  2570. this.Type = resultType;
  2571. }
  2572. public Expression Operand1{
  2573. get{return this.operand1;}
  2574. set{this.operand1 = value;}
  2575. }
  2576. public Expression Operand2{
  2577. get{return this.operand2;}
  2578. set{this.operand2 = value;}
  2579. }
  2580. public Expression Operand3{
  2581. get{return this.operand3;}
  2582. set{this.operand3 = value;}
  2583. }
  2584. }
  2585. public abstract class NaryExpression : Expression{
  2586. #if !FxCop
  2587. public ExpressionList Operands;
  2588. #else
  2589. private ExpressionList operands;
  2590. public ExpressionList Operands {
  2591. get {return this.operands;}
  2592. internal set{this.operands = value;}
  2593. }
  2594. #endif
  2595. protected NaryExpression()
  2596. : base(NodeType.Nop){
  2597. }
  2598. protected NaryExpression(ExpressionList operands, NodeType nodeType)
  2599. : base(nodeType){
  2600. this.Operands = operands;
  2601. }
  2602. }
  2603. #if !MinimalReader
  2604. public class ApplyToAll : BinaryExpression{
  2605. public Local ElementLocal;
  2606. public Method ResultIterator;
  2607. public ApplyToAll()
  2608. : base(null, null, NodeType.ApplyToAll){
  2609. }
  2610. public ApplyToAll(Expression operand1, Expression operand2)
  2611. : base(operand1, operand2, NodeType.ApplyToAll){
  2612. }
  2613. public ApplyToAll(Expression operand1, Expression operand2, SourceContext ctx)
  2614. : base(operand1, operand2, NodeType.ApplyToAll){
  2615. this.SourceContext = ctx;
  2616. }
  2617. }
  2618. #endif
  2619. public class NamedArgument : Expression{
  2620. private bool isCustomAttributeProperty;
  2621. private Identifier name;
  2622. private Expression value;
  2623. private bool valueIsBoxed;
  2624. public NamedArgument()
  2625. : base(NodeType.NamedArgument){
  2626. }
  2627. public NamedArgument(Identifier name, Expression value)
  2628. : base(NodeType.NamedArgument){
  2629. this.Name = name;
  2630. this.Value = value;
  2631. }
  2632. #if !MinimalReader
  2633. public NamedArgument(Identifier name, Expression value, SourceContext ctx)
  2634. : base(NodeType.NamedArgument){
  2635. this.Name = name;
  2636. this.Value = value;
  2637. this.SourceContext = ctx;
  2638. }
  2639. #endif
  2640. public bool IsCustomAttributeProperty{ //TODO: rename this to IsProperty
  2641. get{return this.isCustomAttributeProperty;}
  2642. set{this.isCustomAttributeProperty = value;}
  2643. }
  2644. public Identifier Name{
  2645. get{return this.name;}
  2646. set{this.name = value;}
  2647. }
  2648. public Expression Value{
  2649. get{return this.value;}
  2650. set{this.value = value;}
  2651. }
  2652. public bool ValueIsBoxed{
  2653. get{return this.valueIsBoxed;}
  2654. set{this.valueIsBoxed = value;}
  2655. }
  2656. }
  2657. /// <summary>
  2658. /// This an Expression wrapper for compile time constants. It is assumed to be correct by construction.
  2659. /// In Normalized IR, the wrapped value must be a primitive numeric type or an enum or a string or null.
  2660. /// If used in custom attributes, types are also allowed as well as single dimensional arrays of other allowed types.
  2661. /// If the wrapped value is null, any reference type is allowed, except in custom attributes, where it must be Type or String.
  2662. /// </summary>
  2663. public class Literal : Expression{
  2664. private object value;
  2665. #if !MinimalReader
  2666. public bool TypeWasExplicitlySpecifiedInSource;
  2667. public Expression SourceExpression;
  2668. #endif
  2669. public Literal()
  2670. : base(NodeType.Literal){
  2671. }
  2672. #if !NoReflection
  2673. public Literal(object Value)
  2674. : base(NodeType.Literal){
  2675. this.value = Value;
  2676. }
  2677. #endif
  2678. public Literal(object value, TypeNode type)
  2679. : base(NodeType.Literal){
  2680. this.value = value;
  2681. this.Type = type;
  2682. }
  2683. public Literal(object value, TypeNode type, SourceContext sourceContext)
  2684. : base(NodeType.Literal){
  2685. this.value = value;
  2686. this.SourceContext = sourceContext;
  2687. this.Type = type;
  2688. }
  2689. /// <summary>
  2690. /// Holds the wrapped compile time constant value.
  2691. /// </summary>
  2692. public object Value{
  2693. get{return this.value;}
  2694. }
  2695. public override string ToString(){
  2696. if (this.Value == null) return "Literal for null";
  2697. return this.Value.ToString();
  2698. }
  2699. #if !NoWriter
  2700. public static bool IsNullLiteral(Expression expr){
  2701. Literal lit = expr as Literal;
  2702. if (lit == null) return false;
  2703. if (lit.Type != CoreSystemTypes.Object || lit.Value != null) return false;
  2704. return true;
  2705. }
  2706. //TODO: replace these with properties that freshly allocate them. It appears that Literals sometimes get clobbered.
  2707. public static Literal DoubleOne;
  2708. public static Literal False;
  2709. public static Literal Int32MinusOne;
  2710. public static Literal Int32Zero;
  2711. public static Literal Int32One;
  2712. public static Literal Int32Two;
  2713. public static Literal Int32Sixteen;
  2714. public static Literal Int64Zero;
  2715. public static Literal Int64One;
  2716. public static Literal Null;
  2717. public static Literal SingleOne;
  2718. public static Literal True;
  2719. public static void Initialize(){
  2720. Literal.DoubleOne = new Literal(1.0, CoreSystemTypes.Double);
  2721. Literal.False = new Literal(false, CoreSystemTypes.Boolean);
  2722. Literal.Int32MinusOne = new Literal(-1, CoreSystemTypes.Int32);
  2723. Literal.Int32Zero = new Literal(0, CoreSystemTypes.Int32);
  2724. Literal.Int32One = new Literal(1, CoreSystemTypes.Int32);
  2725. Literal.Int32Two = new Literal(2, CoreSystemTypes.Int32);
  2726. Literal.Int32Sixteen = new Literal(16, CoreSystemTypes.Int32);
  2727. Literal.Int64Zero = new Literal(0L, CoreSystemTypes.Int64);
  2728. Literal.Int64One = new Literal(1L, CoreSystemTypes.Int64);
  2729. Literal.Null = new Literal(null, CoreSystemTypes.Object);
  2730. Literal.SingleOne = new Literal(1.0f, CoreSystemTypes.Single);
  2731. Literal.True = new Literal(true, CoreSystemTypes.Boolean);
  2732. }
  2733. public static void ClearStatics(){
  2734. Literal.DoubleOne = null;
  2735. Literal.False = null;
  2736. Literal.Int32MinusOne = null;
  2737. Literal.Int32Zero = null;
  2738. Literal.Int32One = null;
  2739. Literal.Int32Two = null;
  2740. Literal.Int32Sixteen = null;
  2741. Literal.Int64Zero = null;
  2742. Literal.Int64One = null;
  2743. Literal.Null = null;
  2744. Literal.SingleOne = null;
  2745. Literal.True = null;
  2746. }
  2747. #endif
  2748. }
  2749. public class This : Parameter{
  2750. public This(){
  2751. this.NodeType = NodeType.This;
  2752. this.Name = StandardIds.This;
  2753. }
  2754. public This(TypeNode type){
  2755. this.NodeType = NodeType.This;
  2756. this.Name = StandardIds.This;
  2757. this.Type = type;
  2758. }
  2759. #if !MinimalReader
  2760. public bool IsCtorCall = false;
  2761. public This(SourceContext sctx, bool isCtorCall){
  2762. this.NodeType = NodeType.This;
  2763. this.Name = StandardIds.This;
  2764. this.SourceContext = sctx;
  2765. this.IsCtorCall = isCtorCall;
  2766. }
  2767. public This(TypeNode type, SourceContext sctx){
  2768. this.NodeType = NodeType.This;
  2769. this.Name = StandardIds.This;
  2770. this.Type = type;
  2771. this.SourceContext = sctx;
  2772. }
  2773. public override bool Equals(object obj) {
  2774. ThisBinding binding = obj as ThisBinding;
  2775. return obj == this || binding != null && binding.BoundThis == this;
  2776. }
  2777. public override int GetHashCode(){
  2778. return base.GetHashCode();
  2779. }
  2780. #endif
  2781. #if ExtendedRuntime
  2782. public override bool IsUniversallyDelayed {
  2783. get {
  2784. if (this.DeclaringMethod is InstanceInitializer && this.DeclaringMethod.DeclaringType != null &&
  2785. !this.DeclaringMethod.DeclaringType.IsValueType) {
  2786. // by default, class constructors should be delayed
  2787. return !(this.DeclaringMethod.GetAttribute(ExtendedRuntimeTypes.NotDelayedAttribute) != null);
  2788. }
  2789. return (this.DeclaringMethod.GetAttribute(ExtendedRuntimeTypes.DelayedAttribute) != null);
  2790. }
  2791. }
  2792. #endif
  2793. }
  2794. #if !MinimalReader
  2795. public class ThisBinding : This, IUniqueKey{
  2796. public This/*!*/ BoundThis;
  2797. public ThisBinding(This/*!*/ boundThis, SourceContext sctx) {
  2798. if (boundThis == null) throw new ArgumentNullException("boundThis");
  2799. this.BoundThis = boundThis;
  2800. this.SourceContext = sctx;
  2801. this.Type = boundThis.Type;
  2802. this.Name = boundThis.Name;
  2803. this.TypeExpression = boundThis.TypeExpression;
  2804. this.Attributes = boundThis.Attributes;
  2805. this.DefaultValue = boundThis.DefaultValue;
  2806. this.Flags = boundThis.Flags;
  2807. this.MarshallingInformation = boundThis.MarshallingInformation;
  2808. this.DeclaringMethod = boundThis.DeclaringMethod;
  2809. this.ParameterListIndex = boundThis.ParameterListIndex;
  2810. this.ArgumentListIndex = boundThis.ArgumentListIndex;
  2811. //^ base();
  2812. }
  2813. public override int GetHashCode(){
  2814. return this.BoundThis.GetHashCode();
  2815. }
  2816. public override bool Equals(object obj){
  2817. ThisBinding pb = obj as ThisBinding;
  2818. if (pb != null)
  2819. return this.BoundThis.Equals(pb.BoundThis);
  2820. else
  2821. return this.BoundThis.Equals(obj);
  2822. }
  2823. int IUniqueKey.UniqueId{
  2824. get {return this.BoundThis.UniqueKey;}
  2825. }
  2826. /// <summary>
  2827. /// Must forward type to underlying binding, since ThisBindings get built at times when
  2828. /// the bound This node does not have its final type yet.
  2829. /// </summary>
  2830. public override TypeNode Type {
  2831. get {
  2832. return BoundThis.Type;
  2833. }
  2834. set {
  2835. BoundThis.Type = value;
  2836. }
  2837. }
  2838. }
  2839. public class Base : Expression{
  2840. /// <summary>
  2841. /// When the source uses the C# compatibility mode, base calls cannot be put after non-null
  2842. /// field initialization, but must be put before the body. But the user can specify where
  2843. /// the base ctor call should be performed by using "base;" as a marker. During parsing
  2844. /// this flag is set so the right code transformations can be performed at code generation.
  2845. /// </summary>
  2846. public bool UsedAsMarker;
  2847. public bool IsCtorCall = false;
  2848. public Base()
  2849. : base(NodeType.Base){
  2850. }
  2851. public Base(SourceContext sctx, bool isCtorCall)
  2852. : base(NodeType.Base){
  2853. this.SourceContext = sctx;
  2854. this.IsCtorCall = isCtorCall;
  2855. }
  2856. }
  2857. public class ImplicitThis : Expression{
  2858. public int LexLevel;
  2859. public Class MostNestedScope;
  2860. public ImplicitThis()
  2861. : base(NodeType.ImplicitThis){
  2862. }
  2863. public ImplicitThis(Class mostNestedScope, int lexLevel)
  2864. : base(NodeType.ImplicitThis){
  2865. this.LexLevel = lexLevel;
  2866. this.MostNestedScope = mostNestedScope;
  2867. }
  2868. }
  2869. public class CurrentClosure : Expression{
  2870. public Method Method;
  2871. public CurrentClosure()
  2872. : base(NodeType.CurrentClosure){
  2873. }
  2874. public CurrentClosure(Method method, TypeNode type)
  2875. : base(NodeType.CurrentClosure){
  2876. this.Method = method;
  2877. this.Type = type;
  2878. }
  2879. public CurrentClosure(Method method, TypeNode type, SourceContext sctx)
  2880. : base(NodeType.CurrentClosure){
  2881. this.Method = method;
  2882. this.Type = type;
  2883. this.SourceContext = sctx;
  2884. }
  2885. }
  2886. public class SetterValue : Expression{
  2887. public SetterValue()
  2888. : base(NodeType.SetterValue){
  2889. }
  2890. }
  2891. #endif
  2892. public class Identifier : Expression{
  2893. private int hashCode;
  2894. internal int length;
  2895. private string name;
  2896. private int offset;
  2897. #if !FxCop
  2898. private DocumentText text;
  2899. #endif
  2900. #if !MinimalReader
  2901. public Identifier Prefix;
  2902. #endif
  2903. /// <summary>An identifier with the empty string ("") as its value.</summary>
  2904. public static readonly Identifier/*!*/ Empty = new Identifier("");
  2905. #if !FxCop
  2906. private Identifier(DocumentText/*!*/ text, int offset, int length)
  2907. : base(NodeType.Identifier){
  2908. this.text = text;
  2909. this.offset = offset;
  2910. this.length = length;
  2911. ulong hcode = 0;
  2912. for (int i = offset, n = length+i; i < n; i++){
  2913. char ch = text[i];
  2914. hcode = hcode*17 + ch;
  2915. }
  2916. this.hashCode = ((int)hcode) & int.MaxValue;
  2917. }
  2918. public static Identifier/*!*/ For(SourceContext sctx) {
  2919. DocumentText text = null;
  2920. if (sctx.Document != null) text = sctx.Document.Text;
  2921. if (text == null) text = new DocumentText("");
  2922. Identifier id = new Identifier(text, sctx.StartPos, sctx.EndPos-sctx.StartPos);
  2923. id.SourceContext = sctx;
  2924. return id;
  2925. }
  2926. #endif
  2927. public Identifier(string name)
  2928. : base(NodeType.Identifier){
  2929. if (name == null) name = "";
  2930. this.name = name;
  2931. int n = this.length = name.Length;
  2932. ulong hcode = 0;
  2933. for (int i = 0; i < n; i++){
  2934. char ch = name[i];
  2935. hcode = hcode*17 + ch;
  2936. }
  2937. this.hashCode = ((int)hcode) & int.MaxValue;
  2938. }
  2939. #if !MinimalReader
  2940. public Identifier(string name, SourceContext sctx)
  2941. : this(name){
  2942. this.SourceContext = sctx;
  2943. }
  2944. #endif
  2945. public static Identifier/*!*/ For(string/*!*/ name) {
  2946. return new Identifier(name);
  2947. }
  2948. private unsafe Identifier(byte* pointer, int offset)
  2949. : base(NodeType.Identifier){
  2950. this.offset = offset;
  2951. bool isASCII = true;
  2952. int length = 0;
  2953. ulong hcode = 0;
  2954. for (int i = offset; ; i++){
  2955. byte b = *(pointer+i);
  2956. if (b == 0) break;
  2957. if ((b & 0x80) != 0) isASCII = false;
  2958. hcode = hcode*17 + b;
  2959. length++;
  2960. }
  2961. if (isASCII){
  2962. this.hashCode = ((int)hcode) & int.MaxValue;
  2963. this.length = length;
  2964. this.name = new string((sbyte*)pointer, offset, length, Encoding.ASCII);
  2965. return;
  2966. }
  2967. hcode = 0;
  2968. string name = this.name = new string((sbyte*)pointer, offset, length, Encoding.UTF8);
  2969. for (int i = 0, n = this.length = name.Length; i < n; i++){
  2970. char ch = name[i];
  2971. hcode = hcode*17 + ch;
  2972. }
  2973. this.hashCode = ((int)hcode) & int.MaxValue;
  2974. }
  2975. /// <summary>
  2976. /// Use when pointer+offset points to a null terminated string of UTF8 code points.
  2977. /// </summary>
  2978. internal unsafe static Identifier/*!*/ For(byte* pointer, int offset) {
  2979. //TODO: first look for identifier in cache
  2980. return new Identifier(pointer, offset);
  2981. }
  2982. private unsafe Identifier(byte* pointer, uint length)
  2983. : base(NodeType.Identifier){
  2984. //this.offset = 0;
  2985. this.length = (int)length;
  2986. ulong hcode = 0;
  2987. for (uint i = 0; i < length; i++){
  2988. byte b = *(pointer+i);
  2989. if ((b & 0x80) != 0) goto doUTF8decoding;
  2990. hcode = hcode*17 + b;
  2991. }
  2992. this.hashCode = ((int)hcode) & int.MaxValue;
  2993. this.name = new string((sbyte*)pointer, 0, this.length, Encoding.ASCII);
  2994. return;
  2995. doUTF8decoding:
  2996. string name = this.name = new string((sbyte*)pointer, 0, this.length, Encoding.UTF8);
  2997. for (int i = 0, n = this.length = name.Length; i < n; i++){
  2998. char ch = name[i];
  2999. hcode = hcode*17 + ch;
  3000. }
  3001. this.hashCode = ((int)hcode) & int.MaxValue;
  3002. }
  3003. /// <summary>
  3004. /// Use when pointer points to a string of UTF8 code points of a given length
  3005. /// </summary>
  3006. internal unsafe static Identifier/*!*/ For(byte* pointer, uint length) {
  3007. //TODO: first look for identifier in cache
  3008. return new Identifier(pointer, length);
  3009. }
  3010. private static readonly object/*!*/ Lock = new object();
  3011. private struct CanonicalIdentifier{
  3012. internal string/*!*/ Name;
  3013. internal int UniqueIdKey;
  3014. internal int HashCode;
  3015. internal CanonicalIdentifier(string/*!*/ name, int uniqueIdKey, int hashCode) {
  3016. this.Name = name;
  3017. this.UniqueIdKey = uniqueIdKey;
  3018. this.HashCode = hashCode;
  3019. }
  3020. }
  3021. private static CanonicalIdentifier[]/*!*/ HashTable = new CanonicalIdentifier[16*1024];
  3022. private static int count;
  3023. private int GetUniqueIdKey(){
  3024. lock(Identifier.Lock){
  3025. int hcode = this.hashCode;
  3026. CanonicalIdentifier[] hTable = Identifier.HashTable;
  3027. int length = hTable.Length;
  3028. int i = hcode % length;
  3029. CanonicalIdentifier id = hTable[i];
  3030. while (id.Name != null){
  3031. if (this.HasSameNameAs(id)) return id.UniqueIdKey;
  3032. i = (i+1) % length;
  3033. id = hTable[i];
  3034. }
  3035. int count = Identifier.count;
  3036. int countp1 = count+1;
  3037. Identifier.count = countp1;
  3038. string name = this.Name; //Get a local copy of the name and drop any reference to a DocumentText instance
  3039. hTable[i] = new CanonicalIdentifier(name, countp1, hcode);
  3040. if (countp1 > length/2) Rehash(); //Threshold exceeded, need to rehash
  3041. return countp1;
  3042. }
  3043. }
  3044. private unsafe bool HasSameNameAs(CanonicalIdentifier id) {
  3045. int myLength = this.length;
  3046. int idLength = id.Name.Length;
  3047. if (myLength != idLength) return false;
  3048. string myName = this.name;
  3049. string idName = id.Name;
  3050. #if !FxCop
  3051. if (myName == null){
  3052. int myOffset = this.offset;
  3053. if (this.text != null && this.text.Equals(idName, myOffset, myLength)){
  3054. this.name = idName;
  3055. this.text = null;
  3056. return true;
  3057. }
  3058. return false;
  3059. }
  3060. #endif
  3061. return myName == idName;
  3062. }
  3063. public string/*!*/ Name{ //TODO: need a better name for this property
  3064. get{
  3065. #if !FxCop
  3066. if (this.name != null) return this.name;
  3067. lock(this){
  3068. if (this.name != null) return this.name;
  3069. //^ assume this.text != null;
  3070. int length = this.length;
  3071. int offset = this.offset;
  3072. this.name = this.text.Substring(offset, length);
  3073. this.text = null;
  3074. return this.name;
  3075. }
  3076. #else
  3077. return this.name;
  3078. #endif
  3079. }
  3080. }
  3081. private static void Rehash(){
  3082. CanonicalIdentifier[] hTable = Identifier.HashTable;
  3083. int n = hTable.Length;
  3084. int n2 = n*2;
  3085. CanonicalIdentifier[] newhTable = new CanonicalIdentifier[n2];
  3086. for (int i = 0; i < n; i++){
  3087. CanonicalIdentifier id = hTable[i];
  3088. if (id.Name == null) continue;
  3089. int j = id.HashCode % n2;
  3090. CanonicalIdentifier id2 = newhTable[j];
  3091. while (id2.Name != null){
  3092. j = (j+1) % n2;
  3093. id2 = newhTable[j];
  3094. }
  3095. newhTable[j] = id;
  3096. }
  3097. Identifier.HashTable = newhTable;
  3098. }
  3099. public override string/*!*/ ToString(){
  3100. #if !MinimalReader
  3101. if (this.Prefix != null)
  3102. return this.Prefix.Name+":"+this.Name;
  3103. #endif
  3104. if (this.Name == null) return "";
  3105. return this.Name;
  3106. }
  3107. private int uniqueIdKey;
  3108. /// <summary>
  3109. /// Returns an integer that is the same for every Identifier instance that has the same string value, and that is different from
  3110. /// every other identifier instance that has a different string value. Useful for efficient equality tests when hashing identifiers.
  3111. /// </summary>
  3112. public int UniqueIdKey{
  3113. get{
  3114. int result = this.uniqueIdKey;
  3115. if (result != 0) return result;
  3116. return this.uniqueIdKey = this.GetUniqueIdKey();
  3117. }
  3118. }
  3119. [Obsolete("Use Identifier.UniqueIdKey instead")]
  3120. public new int UniqueKey{
  3121. get{
  3122. int result = this.uniqueIdKey;
  3123. if (result != 0) return result;
  3124. return this.uniqueIdKey = this.GetUniqueIdKey();
  3125. }
  3126. }
  3127. }
  3128. #if !MinimalReader
  3129. public class QualifiedIdentifier : Expression{
  3130. public Identifier Identifier;
  3131. public Expression Qualifier;
  3132. public Expression BoundMember;
  3133. public bool QualifierIsNamespace;
  3134. public QualifiedIdentifier()
  3135. : base(NodeType.QualifiedIdentifer){
  3136. }
  3137. public QualifiedIdentifier(Expression qualifier, Identifier identifier)
  3138. : base(NodeType.QualifiedIdentifer){
  3139. this.Identifier = identifier;
  3140. this.Qualifier = qualifier;
  3141. }
  3142. public QualifiedIdentifier(Expression qualifier, Identifier identifier, SourceContext sourceContext)
  3143. : base(NodeType.QualifiedIdentifer){
  3144. this.Identifier = identifier;
  3145. this.Qualifier = qualifier;
  3146. this.SourceContext = sourceContext;
  3147. }
  3148. public QualifiedIdentifier(Expression qualifier, Identifier identifier, SourceContext sourceContext, bool qualifierIsNamespace)
  3149. : base(NodeType.QualifiedIdentifer){
  3150. this.Identifier = identifier;
  3151. this.Qualifier = qualifier;
  3152. this.SourceContext = sourceContext;
  3153. this.QualifierIsNamespace = qualifierIsNamespace;
  3154. }
  3155. public override string/*!*/ ToString(){
  3156. string str = this.Identifier == null ? "" : this.Identifier.ToString();
  3157. if (this.Qualifier == null) return str;
  3158. string separator = this.QualifierIsNamespace ? "::" : "+";
  3159. return this.Qualifier.ToString()+separator+str;
  3160. }
  3161. }
  3162. public class Quantifier : Expression{
  3163. public NodeType QuantifierType;
  3164. public TypeNode SourceType; // the type of elements the quantifier consumes
  3165. public Comprehension Comprehension;
  3166. public Quantifier()
  3167. : base(NodeType.Quantifier){
  3168. }
  3169. public Quantifier(Comprehension comprehension)
  3170. : base(NodeType.Quantifier){
  3171. this.Comprehension = comprehension;
  3172. }
  3173. public Quantifier(NodeType t, Comprehension comprehension)
  3174. : base(NodeType.Quantifier){
  3175. this.QuantifierType = t;
  3176. this.Comprehension = comprehension;
  3177. }
  3178. }
  3179. public enum ComprehensionBindingMode {In, Gets};
  3180. public class ComprehensionBinding : Expression{
  3181. public ComprehensionBindingMode Mode = ComprehensionBindingMode.In;
  3182. public TypeNode TargetVariableType;
  3183. public TypeNode TargetVariableTypeExpression;
  3184. public Expression TargetVariable;
  3185. public TypeNode AsTargetVariableType;
  3186. public TypeNode AsTargetVariableTypeExpression;
  3187. public Expression SourceEnumerable;
  3188. public BlockScope ScopeForTemporaryVariables;
  3189. public ComprehensionBinding()
  3190. : base(NodeType.ComprehensionBinding){
  3191. }
  3192. }
  3193. public enum ComprehensionMode {Reduction, Comprehension};
  3194. // {1,2,3} ==> Comprehension with BindingsAndFilters = null and Elements = [1,2,3]
  3195. // i.e., for a "display", there are no bindings and the elements have one entry per value in the comprehension
  3196. // { int x in A, P(x); T(x); default } ==> Comprehension with BindingsAndFilters = [int x in A, P(x)] and Elements = [T(x), default]
  3197. // i.e., for "true" comprehensions, the list of elements will always have either one or two elements (two if there is a default)
  3198. public class Comprehension : Expression{
  3199. public ComprehensionMode Mode = ComprehensionMode.Comprehension;
  3200. public ExpressionList BindingsAndFilters;
  3201. public ExpressionList Elements;
  3202. public Node nonEnumerableTypeCtor; // used only when the comprehension should generate code for an IList, e.g.
  3203. public Method AddMethod; // used only when the comprehension should generate code for an IList, e.g.
  3204. public TypeNode TemporaryHackToHoldType;
  3205. public Comprehension()
  3206. : base(NodeType.Comprehension){
  3207. }
  3208. public bool IsDisplay{
  3209. get{
  3210. return this.BindingsAndFilters == null;
  3211. }
  3212. }
  3213. }
  3214. public class NameBinding : Expression{
  3215. public Identifier Identifier;
  3216. public MemberList BoundMembers;
  3217. public Expression BoundMember;
  3218. public int LexLevel;
  3219. public Class MostNestedScope;
  3220. public NameBinding()
  3221. : base(NodeType.NameBinding){
  3222. }
  3223. public NameBinding(Identifier identifier, MemberList boundMembers)
  3224. : base(NodeType.NameBinding){
  3225. this.Identifier = identifier;
  3226. this.BoundMembers = boundMembers;
  3227. }
  3228. public NameBinding(Identifier identifier, MemberList boundMembers, SourceContext sctx)
  3229. : base(NodeType.NameBinding){
  3230. this.Identifier = identifier;
  3231. this.BoundMembers = boundMembers;
  3232. this.SourceContext = sctx;
  3233. }
  3234. public NameBinding(Identifier identifier, MemberList boundMembers, Class mostNestedScope, int lexLevel)
  3235. : base(NodeType.NameBinding){
  3236. this.Identifier = identifier;
  3237. this.BoundMembers = boundMembers;
  3238. this.LexLevel = lexLevel;
  3239. this.MostNestedScope = mostNestedScope;
  3240. }
  3241. public NameBinding(Identifier identifier, MemberList boundMembers, Class mostNestedScope, int lexLevel, SourceContext sctx)
  3242. : base(NodeType.NameBinding) {
  3243. this.Identifier = identifier;
  3244. this.BoundMembers = boundMembers;
  3245. this.LexLevel = lexLevel;
  3246. this.MostNestedScope = mostNestedScope;
  3247. this.SourceContext = sctx;
  3248. }
  3249. public override string ToString() {
  3250. return this.Identifier == null ? "" : this.Identifier.ToString();
  3251. }
  3252. }
  3253. public class TemplateInstance : Expression{
  3254. public Expression Expression;
  3255. public TypeNodeList TypeArguments;
  3256. public TypeNodeList TypeArgumentExpressions;
  3257. public bool IsMethodTemplate;
  3258. public MemberList BoundMembers;
  3259. public TemplateInstance()
  3260. : this(null, null){
  3261. }
  3262. public TemplateInstance(Expression expression, TypeNodeList typeArguments)
  3263. : base(NodeType.TemplateInstance){
  3264. this.Expression = expression;
  3265. this.TypeArguments = typeArguments;
  3266. }
  3267. }
  3268. public class StackAlloc : Expression{
  3269. public TypeNode ElementType;
  3270. public TypeNode ElementTypeExpression;
  3271. public Expression NumberOfElements;
  3272. public StackAlloc()
  3273. : base(NodeType.StackAlloc){
  3274. }
  3275. public StackAlloc(TypeNode elementType, Expression numberOfElements, SourceContext sctx)
  3276. : base(NodeType.StackAlloc){
  3277. this.ElementType = this.ElementTypeExpression = elementType;
  3278. this.NumberOfElements = numberOfElements;
  3279. this.SourceContext = sctx;
  3280. }
  3281. }
  3282. #endif
  3283. public class MethodCall : NaryExpression{
  3284. private Expression callee;
  3285. private TypeNode constraint;
  3286. private bool isTailCall;
  3287. #if !MinimalReader
  3288. public Expression CalleeExpression;
  3289. public bool GiveErrorIfSpecialNameMethod;
  3290. public bool ArgumentListIsIncomplete;
  3291. public MethodCall(){
  3292. this.NodeType = NodeType.MethodCall;
  3293. }
  3294. public MethodCall(Expression callee, ExpressionList arguments)
  3295. : base(arguments, NodeType.MethodCall){
  3296. this.callee = this.CalleeExpression = callee;
  3297. this.isTailCall = false;
  3298. }
  3299. #endif
  3300. public MethodCall(Expression callee, ExpressionList arguments, NodeType typeOfCall)
  3301. : base(arguments, typeOfCall){
  3302. this.callee = callee;
  3303. #if !MinimalReader
  3304. this.CalleeExpression = callee;
  3305. #endif
  3306. //this.isTailCall = false;
  3307. }
  3308. #if !MinimalReader
  3309. public MethodCall(Expression callee, ExpressionList arguments, NodeType typeOfCall, TypeNode resultType)
  3310. : this(callee, arguments, typeOfCall){
  3311. this.Type = resultType;
  3312. }
  3313. public MethodCall(Expression callee, ExpressionList arguments, NodeType typeOfCall, TypeNode resultType, SourceContext sctx)
  3314. : this(callee, arguments, typeOfCall, resultType){
  3315. this.SourceContext = sctx;
  3316. }
  3317. #endif
  3318. public Expression Callee{
  3319. get{return this.callee;}
  3320. set{this.callee = value;}
  3321. }
  3322. public bool IsTailCall{
  3323. get{return this.isTailCall;}
  3324. set{this.isTailCall = value;}
  3325. }
  3326. public TypeNode Constraint{
  3327. get{return this.constraint;}
  3328. set{this.constraint = value;}
  3329. }
  3330. }
  3331. public class Construct : NaryExpression{
  3332. private Expression constructor;
  3333. #if !MinimalReader
  3334. public Expression Owner;
  3335. #endif
  3336. public Construct(){
  3337. this.NodeType = NodeType.Construct;
  3338. }
  3339. public Construct(Expression constructor, ExpressionList arguments)
  3340. : base(arguments, NodeType.Construct){
  3341. this.constructor = constructor;
  3342. }
  3343. #if !MinimalReader
  3344. public Construct(Expression constructor, ExpressionList arguments, SourceContext sctx)
  3345. : base(arguments, NodeType.Construct){
  3346. this.constructor = constructor;
  3347. this.SourceContext = sctx;
  3348. }
  3349. public Construct(Expression constructor, ExpressionList arguments, TypeNode type)
  3350. : base(arguments, NodeType.Construct){
  3351. this.constructor = constructor;
  3352. this.Type = type;
  3353. }
  3354. public Construct(Expression constructor, ExpressionList arguments, TypeNode type, SourceContext sctx)
  3355. : base(arguments, NodeType.Construct) {
  3356. this.constructor = constructor;
  3357. this.Type = type;
  3358. this.SourceContext = sctx;
  3359. }
  3360. #endif
  3361. public Expression Constructor{
  3362. get{return this.constructor;}
  3363. set{this.constructor = value;}
  3364. }
  3365. }
  3366. public class ConstructArray : NaryExpression{
  3367. private TypeNode elementType;
  3368. private int rank;
  3369. #if !MinimalReader
  3370. public TypeNode ElementTypeExpression;
  3371. public ExpressionList Initializers;
  3372. public Expression Owner;
  3373. #endif
  3374. public ConstructArray(){
  3375. this.NodeType = NodeType.ConstructArray;
  3376. this.rank = 1;
  3377. }
  3378. public ConstructArray(TypeNode elementType, ExpressionList sizes, ExpressionList initializers)
  3379. : base(sizes, NodeType.ConstructArray){
  3380. this.elementType = elementType;
  3381. this.Operands = sizes;
  3382. this.rank = sizes == null ? 1 : sizes.Count;
  3383. #if !MinimalReader
  3384. this.Initializers = initializers;
  3385. #endif
  3386. }
  3387. #if !MinimalReader
  3388. public ConstructArray(TypeNode elementType, ExpressionList initializers)
  3389. : base(null, NodeType.ConstructArray){
  3390. this.elementType = elementType;
  3391. this.Initializers = initializers;
  3392. this.rank = 1;
  3393. if (elementType != null)
  3394. this.Type = elementType.GetArrayType(1);
  3395. }
  3396. public ConstructArray(TypeNode elementType, int rank, ExpressionList initializers)
  3397. : base(null, NodeType.ConstructArray){
  3398. this.elementType = elementType;
  3399. this.Initializers = initializers;
  3400. this.rank = rank;
  3401. if (elementType != null)
  3402. this.Type = elementType.GetArrayType(1);
  3403. }
  3404. #endif
  3405. public TypeNode ElementType{
  3406. get{return this.elementType;}
  3407. set{this.elementType = value;}
  3408. }
  3409. public int Rank{
  3410. get{return this.rank;}
  3411. set{this.rank = value;}
  3412. }
  3413. }
  3414. #if !MinimalReader
  3415. public class ConstructFlexArray : NaryExpression{
  3416. public TypeNode ElementType;
  3417. public TypeNode ElementTypeExpression;
  3418. public ExpressionList Initializers;
  3419. public ConstructFlexArray(){
  3420. this.NodeType = NodeType.ConstructFlexArray;
  3421. }
  3422. public ConstructFlexArray(TypeNode elementType, ExpressionList sizes, ExpressionList initializers)
  3423. : base(sizes, NodeType.ConstructFlexArray){
  3424. this.ElementType = elementType;
  3425. this.Operands = sizes;
  3426. this.Initializers = initializers;
  3427. }
  3428. }
  3429. public class ConstructDelegate : Expression{
  3430. public TypeNode DelegateType;
  3431. public TypeNode DelegateTypeExpression;
  3432. public Identifier MethodName;
  3433. public Expression TargetObject;
  3434. public ConstructDelegate()
  3435. : base(NodeType.ConstructDelegate){
  3436. }
  3437. public ConstructDelegate(TypeNode delegateType, Expression targetObject, Identifier methodName)
  3438. : base(NodeType.ConstructDelegate) {
  3439. this.DelegateType = delegateType;
  3440. this.MethodName = methodName;
  3441. this.TargetObject = targetObject;
  3442. }
  3443. public ConstructDelegate(TypeNode delegateType, Expression targetObject, Identifier methodName, SourceContext sctx)
  3444. : base(NodeType.ConstructDelegate){
  3445. this.DelegateType = delegateType;
  3446. this.MethodName = methodName;
  3447. this.TargetObject = targetObject;
  3448. this.SourceContext = sctx;
  3449. }
  3450. }
  3451. public class ConstructIterator : Expression{
  3452. public Class State;
  3453. public Block Body;
  3454. public TypeNode ElementType;
  3455. public ConstructIterator()
  3456. : base(NodeType.ConstructIterator){
  3457. }
  3458. public ConstructIterator(Class state, Block body, TypeNode elementType, TypeNode type)
  3459. : base(NodeType.ConstructIterator){
  3460. this.State = state;
  3461. this.Body = body;
  3462. this.ElementType = elementType;
  3463. this.Type = type;
  3464. }
  3465. }
  3466. public class ConstructTuple : Expression{
  3467. public FieldList Fields;
  3468. public ConstructTuple()
  3469. : base(NodeType.ConstructTuple){
  3470. }
  3471. }
  3472. public class CoerceTuple : ConstructTuple{
  3473. public Expression OriginalTuple;
  3474. public Local Temp;
  3475. public CoerceTuple(){
  3476. this.NodeType = NodeType.CoerceTuple;
  3477. }
  3478. }
  3479. #endif
  3480. public class Indexer : NaryExpression{
  3481. #if !MinimalReader
  3482. public Property CorrespondingDefaultIndexedProperty;
  3483. public bool ArgumentListIsIncomplete;
  3484. #endif
  3485. public Indexer(){
  3486. this.NodeType = NodeType.Indexer;
  3487. }
  3488. public Indexer(Expression @object, ExpressionList arguments)
  3489. : base(arguments, NodeType.Indexer){
  3490. this.@object = @object;
  3491. }
  3492. #if !MinimalReader
  3493. public Indexer(Expression Object, ExpressionList arguments, SourceContext sctx)
  3494. : base(arguments, NodeType.Indexer){
  3495. this.@object = Object;
  3496. this.SourceContext = sctx;
  3497. }
  3498. public Indexer(Expression Object, ExpressionList arguments, TypeNode elementType)
  3499. : base(arguments, NodeType.Indexer){
  3500. this.@object = Object;
  3501. this.elementType = this.Type = elementType;
  3502. }
  3503. public Indexer(Expression Object, ExpressionList arguments, TypeNode elementType, SourceContext sctx)
  3504. : base(arguments, NodeType.Indexer){
  3505. this.@object = Object;
  3506. this.elementType = this.Type = elementType;
  3507. this.SourceContext = sctx;
  3508. }
  3509. #endif
  3510. private Expression @object;
  3511. public Expression Object{
  3512. get{return this.@object;}
  3513. set{this.@object = value;}
  3514. }
  3515. private TypeNode elementType;
  3516. /// <summary>
  3517. /// This type is normally expected to be the same the value of Type. However, if the indexer applies to an array of enums, then
  3518. /// Type will be the enum type and ElementType will be the underlying type of the enum.
  3519. /// </summary>
  3520. public TypeNode ElementType{
  3521. get{return this.elementType;}
  3522. set{this.elementType = value;}
  3523. }
  3524. }
  3525. #if !MinimalReader
  3526. public class CollectionEnumerator : Expression{
  3527. public Expression Collection;
  3528. public Method DefaultIndexerGetter;
  3529. public Method LengthPropertyGetter;
  3530. public Method GetEnumerator;
  3531. public Method MoveNext;
  3532. public Method GetCurrent;
  3533. public Local ElementLocal;
  3534. public Expression ElementCoercion;
  3535. public CollectionEnumerator()
  3536. : base(NodeType.CollectionEnumerator){
  3537. }
  3538. }
  3539. /// <summary>
  3540. /// An expression that is used on the left hand as well as the right hand side of an assignment statement. For example, e in (e += 1).
  3541. /// </summary>
  3542. public class LRExpression : Expression{
  3543. public Expression Expression;
  3544. public LocalList Temporaries;
  3545. public ExpressionList SubexpressionsToEvaluateOnce;
  3546. public LRExpression(Expression/*!*/ expression)
  3547. : base(NodeType.LRExpression){
  3548. this.Expression = expression;
  3549. this.Type = expression.Type;
  3550. }
  3551. }
  3552. public class AssignmentExpression : Expression{
  3553. public Statement AssignmentStatement;
  3554. public AssignmentExpression()
  3555. : base(NodeType.AssignmentExpression){
  3556. }
  3557. public AssignmentExpression(AssignmentStatement assignment)
  3558. : base(NodeType.AssignmentExpression){
  3559. this.AssignmentStatement = assignment;
  3560. }
  3561. }
  3562. #endif
  3563. #if !MinimalReader || FxCop
  3564. public class BlockExpression : Expression{
  3565. public Block Block;
  3566. public BlockExpression()
  3567. : base(NodeType.BlockExpression){
  3568. }
  3569. public BlockExpression(Block block)
  3570. : base(NodeType.BlockExpression){
  3571. this.Block = block;
  3572. }
  3573. public BlockExpression(Block block, TypeNode type)
  3574. : base(NodeType.BlockExpression){
  3575. this.Block = block;
  3576. this.Type = type;
  3577. }
  3578. public BlockExpression(Block block, TypeNode type, SourceContext sctx)
  3579. : base(NodeType.BlockExpression){
  3580. this.Block = block;
  3581. this.Type = type;
  3582. this.SourceContext = sctx;
  3583. }
  3584. }
  3585. #endif
  3586. #if !MinimalReader
  3587. public class AnonymousNestedFunction : Expression{
  3588. public ParameterList Parameters;
  3589. public Block Body;
  3590. public Method Method;
  3591. public Expression Invocation;
  3592. public AnonymousNestedFunction()
  3593. : base(NodeType.AnonymousNestedFunction){
  3594. }
  3595. public AnonymousNestedFunction(ParameterList parameters, Block body)
  3596. : base(NodeType.AnonymousNestedFunction){
  3597. this.Parameters = parameters;
  3598. this.Body = body;
  3599. }
  3600. public AnonymousNestedFunction(ParameterList parameters, Block body, SourceContext sctx)
  3601. : base(NodeType.AnonymousNestedFunction){
  3602. this.Parameters = parameters;
  3603. this.Body = body;
  3604. this.SourceContext = sctx;
  3605. }
  3606. }
  3607. #endif
  3608. public class Instruction : Node{
  3609. private OpCode opCode;
  3610. private int offset;
  3611. private object value;
  3612. public Instruction()
  3613. : base(NodeType.Instruction){
  3614. }
  3615. public Instruction(OpCode opCode, int offset)
  3616. : this(opCode, offset, null){
  3617. }
  3618. public Instruction(OpCode opCode, int offset, object value)
  3619. : base(NodeType.Instruction){
  3620. this.opCode = opCode;
  3621. this.offset = offset;
  3622. this.value = value;
  3623. }
  3624. /// <summary>The actual value of the opcode</summary>
  3625. public OpCode OpCode{
  3626. get{return this.opCode;}
  3627. set{this.opCode = value;}
  3628. }
  3629. /// <summary>The offset from the start of the instruction stream of a method</summary>
  3630. public int Offset{
  3631. get{return this.offset;}
  3632. set{this.offset = value;}
  3633. }
  3634. /// <summary>Immediate data such as a string, the address of a branch target, or a metadata reference, such as a Field</summary>
  3635. public object Value{
  3636. get{return this.value;}
  3637. set{this.value = value;}
  3638. }
  3639. }
  3640. public class Statement : Node{
  3641. #if FxCop
  3642. internal int ILOffset;
  3643. #endif
  3644. #if !FxCop && ILOFFSETS
  3645. public int ILOffset;
  3646. #endif
  3647. public Statement(NodeType nodeType)
  3648. : base(nodeType){
  3649. }
  3650. #if !MinimalReader
  3651. public Statement(NodeType nodeType, SourceContext sctx)
  3652. : base(nodeType) {
  3653. this.SourceContext = sctx;
  3654. }
  3655. #endif
  3656. }
  3657. public class Block : Statement{
  3658. private StatementList statements;
  3659. #if !MinimalReader
  3660. public bool Checked;
  3661. public bool SuppressCheck;
  3662. #endif
  3663. #if !MinimalReader || !NoWriter
  3664. public bool HasLocals;
  3665. #endif
  3666. #if !MinimalReader
  3667. public bool IsUnsafe;
  3668. public BlockScope Scope;
  3669. #endif
  3670. public Block()
  3671. : base(NodeType.Block){
  3672. }
  3673. public Block(StatementList statements)
  3674. : base(NodeType.Block){
  3675. this.statements = statements;
  3676. }
  3677. #if !MinimalReader
  3678. public Block(StatementList statements, SourceContext sourceContext)
  3679. : base(NodeType.Block){
  3680. this.SourceContext = sourceContext;
  3681. this.statements = statements;
  3682. }
  3683. public Block(StatementList statements, bool Checked, bool SuppressCheck, bool IsUnsafe)
  3684. : base(NodeType.Block){
  3685. this.Checked = Checked;
  3686. this.IsUnsafe = IsUnsafe;
  3687. this.SuppressCheck = SuppressCheck;
  3688. this.statements = statements;
  3689. }
  3690. public Block(StatementList statements, SourceContext sourceContext, bool Checked, bool SuppressCheck, bool IsUnsafe)
  3691. : base(NodeType.Block){
  3692. this.Checked = Checked;
  3693. this.IsUnsafe = IsUnsafe;
  3694. this.SuppressCheck = SuppressCheck;
  3695. this.SourceContext = sourceContext;
  3696. this.statements = statements;
  3697. }
  3698. public override string ToString() {
  3699. return "B#" + this.UniqueKey.ToString();
  3700. }
  3701. #endif
  3702. public StatementList Statements{
  3703. get{return this.statements;}
  3704. set{this.statements = value;}
  3705. }
  3706. }
  3707. #if !MinimalReader
  3708. public class LabeledStatement : Block{
  3709. public Identifier Label;
  3710. public Statement Statement;
  3711. public LabeledStatement(){
  3712. this.NodeType = NodeType.LabeledStatement;
  3713. }
  3714. }
  3715. public class FunctionDeclaration : Statement{
  3716. public Identifier Name;
  3717. public ParameterList Parameters;
  3718. public TypeNode ReturnType;
  3719. public TypeNode ReturnTypeExpression;
  3720. public Block Body;
  3721. public Method Method;
  3722. public FunctionDeclaration()
  3723. : base(NodeType.FunctionDeclaration){
  3724. }
  3725. public FunctionDeclaration(Identifier name, ParameterList parameters, TypeNode returnType, Block body)
  3726. : base(NodeType.FunctionDeclaration){
  3727. this.Name = name;
  3728. this.Parameters = parameters;
  3729. this.ReturnType = returnType;
  3730. this.Body = body;
  3731. }
  3732. }
  3733. public class Assertion : Statement{
  3734. public Expression Condition;
  3735. // a string that a user wants associated with the assertion
  3736. public Literal userMessage;
  3737. public Assertion()
  3738. : base(NodeType.Assertion){
  3739. }
  3740. public Assertion(Expression condition)
  3741. : base(NodeType.Assertion){
  3742. this.Condition = condition;
  3743. }
  3744. }
  3745. public class Assumption : Statement{
  3746. public Expression Condition;
  3747. // a string that a user wants associated with the assumption
  3748. public Literal userMessage;
  3749. public Assumption()
  3750. : base(NodeType.Assumption){
  3751. }
  3752. public Assumption(Expression condition)
  3753. : base(NodeType.Assumption){
  3754. this.Condition = condition;
  3755. }
  3756. }
  3757. #endif
  3758. public class AssignmentStatement : Statement{
  3759. private NodeType @operator;
  3760. private Expression source;
  3761. private Expression target;
  3762. #if !MinimalReader
  3763. public Method OperatorOverload;
  3764. ///<summary>A Type two which both operands must be coerced before carrying out the operation (if any).</summary>
  3765. public TypeNode UnifiedType;
  3766. #endif
  3767. public AssignmentStatement()
  3768. : base(NodeType.AssignmentStatement){
  3769. this.Operator = NodeType.Nop;
  3770. }
  3771. public AssignmentStatement(Expression target, Expression source)
  3772. : this(target, source, NodeType.Nop){
  3773. }
  3774. #if !MinimalReader
  3775. public AssignmentStatement(Expression target, Expression source, SourceContext context)
  3776. : this(target, source, NodeType.Nop){
  3777. this.SourceContext = context;
  3778. }
  3779. #endif
  3780. public AssignmentStatement(Expression target, Expression source, NodeType @operator)
  3781. : base(NodeType.AssignmentStatement){
  3782. this.target = target;
  3783. this.source = source;
  3784. this.@operator = @operator;
  3785. }
  3786. #if !MinimalReader
  3787. public AssignmentStatement(Expression target, Expression source, NodeType Operator, SourceContext context)
  3788. : this(target, source, Operator){
  3789. this.SourceContext = context;
  3790. }
  3791. #endif
  3792. public NodeType Operator{
  3793. get{return this.@operator;}
  3794. set{this.@operator = value;}
  3795. }
  3796. public Expression Source{
  3797. get{return this.source;}
  3798. set{this.source = value;}
  3799. }
  3800. public Expression Target{
  3801. get{return this.target;}
  3802. set{this.target = value;}
  3803. }
  3804. }
  3805. public class ExpressionStatement : Statement{
  3806. private Expression expression;
  3807. public ExpressionStatement()
  3808. : base(NodeType.ExpressionStatement){
  3809. }
  3810. public ExpressionStatement(Expression expression)
  3811. : base(NodeType.ExpressionStatement){
  3812. this.Expression = expression;
  3813. }
  3814. #if !MinimalReader
  3815. public ExpressionStatement(Expression expression, SourceContext sctx)
  3816. : base(NodeType.ExpressionStatement){
  3817. this.Expression = expression;
  3818. this.SourceContext = sctx;
  3819. }
  3820. #endif
  3821. public Expression Expression{
  3822. get{return this.expression;}
  3823. set{this.expression = value;}
  3824. }
  3825. }
  3826. public class Branch : Statement{
  3827. private Expression condition;
  3828. private bool leavesExceptionBlock;
  3829. internal bool shortOffset;
  3830. private Block target;
  3831. public bool BranchIfUnordered;
  3832. public Branch()
  3833. : base(NodeType.Branch){
  3834. }
  3835. #if !MinimalReader
  3836. public Branch(Expression condition, Block target)
  3837. : this(condition, target, false, false, false){
  3838. }
  3839. public Branch(Expression condition, Block target, SourceContext sourceContext)
  3840. : this(condition, target, false, false, false){
  3841. this.SourceContext = sourceContext;
  3842. }
  3843. public Branch(Expression condition, Block target, SourceContext sourceContext, bool unordered)
  3844. : this(condition, target, false, false, false){
  3845. this.BranchIfUnordered = unordered;
  3846. this.SourceContext = sourceContext;
  3847. }
  3848. #endif
  3849. public Branch(Expression condition, Block target, bool shortOffset, bool unordered, bool leavesExceptionBlock)
  3850. : base(NodeType.Branch){
  3851. this.BranchIfUnordered = unordered;
  3852. this.condition = condition;
  3853. this.leavesExceptionBlock = leavesExceptionBlock;
  3854. this.shortOffset = shortOffset;
  3855. this.target = target;
  3856. }
  3857. public Expression Condition{
  3858. get{return this.condition;}
  3859. set{this.condition = value; }
  3860. }
  3861. public bool LeavesExceptionBlock{
  3862. get{return this.leavesExceptionBlock;}
  3863. set{this.leavesExceptionBlock = value;}
  3864. }
  3865. public bool ShortOffset{
  3866. get{return this.shortOffset;}
  3867. set{this.shortOffset = value;}
  3868. }
  3869. public Block Target{
  3870. get{return this.target;}
  3871. set{this.target = value; }
  3872. }
  3873. }
  3874. #if FxCop
  3875. public class ReturnNode : ExpressionStatement{
  3876. public ReturnNode()
  3877. #else
  3878. public class Return : ExpressionStatement{
  3879. public Return()
  3880. #endif
  3881. : base(){
  3882. this.NodeType = NodeType.Return;
  3883. }
  3884. #if FxCop
  3885. public ReturnNode(Expression expression)
  3886. #else
  3887. public Return(Expression expression)
  3888. #endif
  3889. : base(expression){
  3890. this.NodeType = NodeType.Return;
  3891. }
  3892. #if !MinimalReader
  3893. public Return(SourceContext sctx)
  3894. : base() {
  3895. this.NodeType = NodeType.Return;
  3896. this.SourceContext = sctx;
  3897. }
  3898. public Return(Expression expression, SourceContext sctx)
  3899. : base(expression) {
  3900. this.NodeType = NodeType.Return;
  3901. this.SourceContext = sctx;
  3902. }
  3903. #endif
  3904. }
  3905. #if !MinimalReader
  3906. /// <summary>
  3907. /// Represents the return value in a post condition
  3908. /// </summary>
  3909. public class ReturnValue : Expression
  3910. {
  3911. public ReturnValue() : base(NodeType.ReturnValue)
  3912. { }
  3913. public ReturnValue(SourceContext sc)
  3914. : this()
  3915. {
  3916. this.SourceContext = sc;
  3917. }
  3918. public ReturnValue(TypeNode returnType, SourceContext sc)
  3919. : this(sc)
  3920. {
  3921. this.Type = returnType;
  3922. }
  3923. public ReturnValue(TypeNode returnType)
  3924. : this()
  3925. {
  3926. this.Type = returnType;
  3927. }
  3928. }
  3929. public class Yield : ExpressionStatement{
  3930. public Yield()
  3931. : base(){
  3932. this.NodeType = NodeType.Yield;
  3933. }
  3934. public Yield(Expression expression)
  3935. : base(expression){
  3936. this.NodeType = NodeType.Yield;
  3937. }
  3938. public Yield(Expression expression, SourceContext sctx)
  3939. : base(expression){
  3940. this.NodeType = NodeType.Yield;
  3941. this.SourceContext = sctx;
  3942. }
  3943. }
  3944. public class Try : Statement{
  3945. private CatchList catchers;
  3946. private FilterList filters;
  3947. private FaultHandlerList faultHandlers;
  3948. private Finally finallyClause;
  3949. private Block tryBlock;
  3950. public Try()
  3951. : base(NodeType.Try){
  3952. }
  3953. public Try(Block tryBlock, CatchList catchers, FilterList filters, FaultHandlerList faultHandlers, Finally Finally)
  3954. : base(NodeType.Try){
  3955. this.catchers = catchers;
  3956. this.faultHandlers = faultHandlers;
  3957. this.filters = filters;
  3958. this.finallyClause = Finally;
  3959. this.tryBlock = tryBlock;
  3960. }
  3961. public CatchList Catchers{
  3962. get{return this.catchers;}
  3963. set{this.catchers = value;}
  3964. }
  3965. public FilterList Filters{
  3966. get{return this.filters;}
  3967. set{this.filters = value;}
  3968. }
  3969. public FaultHandlerList FaultHandlers{
  3970. get{return this.faultHandlers;}
  3971. set{this.faultHandlers = value;}
  3972. }
  3973. public Finally Finally{
  3974. get{return this.finallyClause;}
  3975. set{this.finallyClause = value;}
  3976. }
  3977. public Block TryBlock{
  3978. get{return this.tryBlock;}
  3979. set{this.tryBlock = value;}
  3980. }
  3981. }
  3982. public class Catch : Statement{
  3983. private Block block;
  3984. private TypeNode type;
  3985. private Expression variable;
  3986. public TypeNode TypeExpression;
  3987. public Catch()
  3988. : base(NodeType.Catch){
  3989. }
  3990. public Catch(Block block, Expression variable, TypeNode type)
  3991. : base(NodeType.Catch){
  3992. this.block = block;
  3993. this.variable = variable;
  3994. this.type = type;
  3995. }
  3996. public Block Block{
  3997. get{return this.block;}
  3998. set{this.block = value;}
  3999. }
  4000. public TypeNode Type{
  4001. get{return this.type;}
  4002. set{this.type = value;}
  4003. }
  4004. public Expression Variable{
  4005. get{return this.variable;}
  4006. set{this.variable = value;}
  4007. }
  4008. }
  4009. public class Finally : Statement{
  4010. private Block block;
  4011. public Finally()
  4012. : base(NodeType.Finally){
  4013. }
  4014. public Finally(Block block)
  4015. : base(NodeType.Finally){
  4016. this.block = block;
  4017. }
  4018. public Block Block{
  4019. get{return this.block;}
  4020. set{this.block = value;}
  4021. }
  4022. }
  4023. #endif
  4024. public class EndFinally : Statement{
  4025. public EndFinally()
  4026. : base(NodeType.EndFinally){
  4027. }
  4028. }
  4029. #if !MinimalReader || FxCop
  4030. public class Filter : Statement{
  4031. private Block block;
  4032. private Expression expression;
  4033. #if FxCop
  4034. internal int handlerEnd;
  4035. #endif
  4036. public Filter()
  4037. : base(NodeType.Filter){
  4038. }
  4039. public Filter(Block block, Expression expression)
  4040. : base(NodeType.Filter){
  4041. this.block = block;
  4042. this.expression = expression;
  4043. }
  4044. public Block Block{
  4045. get{return this.block;}
  4046. set{this.block = value;}
  4047. }
  4048. public Expression Expression{
  4049. get{return this.expression;}
  4050. set{this.expression = value;}
  4051. }
  4052. }
  4053. #endif
  4054. public class EndFilter : Statement{
  4055. private Expression value;
  4056. public EndFilter()
  4057. : base(NodeType.EndFilter){
  4058. }
  4059. public EndFilter(Expression value)
  4060. : base(NodeType.EndFilter){
  4061. this.value = value;
  4062. }
  4063. public Expression Value{
  4064. get{return this.value;}
  4065. set{this.value = value;}
  4066. }
  4067. }
  4068. #if !MinimalReader || FxCop
  4069. public class FaultHandler : Statement{
  4070. private Block block;
  4071. #if FxCop
  4072. internal int handlerEnd;
  4073. #endif
  4074. public FaultHandler()
  4075. : base(NodeType.FaultHandler){
  4076. }
  4077. public FaultHandler(Block block)
  4078. : base(NodeType.FaultHandler){
  4079. this.block = block;
  4080. }
  4081. public Block Block{
  4082. get{return this.block;}
  4083. set{this.block = value;}
  4084. }
  4085. }
  4086. #endif
  4087. #if FxCop
  4088. public class ThrowNode : Statement{
  4089. #else
  4090. public class Throw : Statement{
  4091. #endif
  4092. private Expression expression;
  4093. #if FxCop
  4094. public ThrowNode()
  4095. : base(NodeType.Throw){
  4096. }
  4097. public ThrowNode(Expression expression)
  4098. : base(NodeType.Throw){
  4099. this.expression = expression;
  4100. }
  4101. #else
  4102. public Throw()
  4103. : base(NodeType.Throw){
  4104. }
  4105. public Throw(Expression expression)
  4106. : base(NodeType.Throw){
  4107. this.expression = expression;
  4108. }
  4109. #endif
  4110. #if !MinimalReader
  4111. public Throw(Expression expression, SourceContext context)
  4112. : base(NodeType.Throw){
  4113. this.expression = expression;
  4114. this.SourceContext = context;
  4115. }
  4116. #endif
  4117. public Expression Expression{
  4118. get{return this.expression;}
  4119. set{this.expression = value;}
  4120. }
  4121. }
  4122. #if !MinimalReader
  4123. public class If : Statement{
  4124. public Expression Condition;
  4125. public Block TrueBlock;
  4126. public Block FalseBlock;
  4127. public SourceContext ConditionContext;
  4128. public SourceContext ElseContext;
  4129. public SourceContext EndIfContext;
  4130. public If()
  4131. : base(NodeType.If){
  4132. }
  4133. public If(Expression condition, Block trueBlock, Block falseBlock)
  4134. : base(NodeType.If){
  4135. this.Condition = condition;
  4136. if (condition != null)
  4137. this.ConditionContext = condition.SourceContext;
  4138. this.TrueBlock = trueBlock;
  4139. this.FalseBlock = falseBlock;
  4140. }
  4141. }
  4142. public class For : Statement{
  4143. public Block Body;
  4144. public Expression Condition;
  4145. public StatementList Incrementer;
  4146. public StatementList Initializer;
  4147. public ExpressionList Invariants;
  4148. public For()
  4149. : base(NodeType.For){
  4150. }
  4151. public For(StatementList initializer, Expression condition, StatementList incrementer, Block body)
  4152. : base(NodeType.For){
  4153. this.Body = body;
  4154. this.Condition = condition;
  4155. this.Incrementer = incrementer;
  4156. this.Initializer = initializer;
  4157. }
  4158. }
  4159. public class ForEach : Statement{
  4160. public Block Body;
  4161. public Expression SourceEnumerable;
  4162. public BlockScope ScopeForTemporaryVariables;
  4163. public Expression TargetVariable;
  4164. public TypeNode TargetVariableType;
  4165. public TypeNode TargetVariableTypeExpression;
  4166. public Expression InductionVariable;
  4167. public ExpressionList Invariants;
  4168. public bool StatementTerminatesNormallyIfEnumerableIsNull = true;
  4169. public bool StatementTerminatesNormallyIfEnumeratorIsNull = true;
  4170. public ForEach()
  4171. : base(NodeType.ForEach){
  4172. }
  4173. public ForEach(TypeNode targetVariableType, Expression targetVariable, Expression sourceEnumerable, Block body)
  4174. : base(NodeType.ForEach){
  4175. this.TargetVariable = targetVariable;
  4176. this.TargetVariableType = targetVariableType;
  4177. this.SourceEnumerable = sourceEnumerable;
  4178. this.Body = body;
  4179. }
  4180. }
  4181. public class Exit : Statement{
  4182. public Literal Level;
  4183. public Exit()
  4184. : base(NodeType.Exit){
  4185. }
  4186. public Exit(Literal level)
  4187. : base(NodeType.Exit){
  4188. this.Level = level;
  4189. }
  4190. }
  4191. public class Continue : Statement{
  4192. public Literal Level;
  4193. public Continue()
  4194. : base(NodeType.Continue){
  4195. }
  4196. public Continue(Literal level)
  4197. : base(NodeType.Continue){
  4198. this.Level = level;
  4199. }
  4200. }
  4201. public class Switch : Statement{
  4202. public SwitchCaseList Cases;
  4203. public Expression Expression;
  4204. public Local Nullable;
  4205. public Expression NullableExpression;
  4206. public BlockScope Scope;
  4207. public Switch()
  4208. : base(NodeType.Switch){
  4209. }
  4210. public Switch(Expression expression, SwitchCaseList cases)
  4211. : base(NodeType.Switch){
  4212. this.Cases = cases;
  4213. this.Expression = expression;
  4214. }
  4215. }
  4216. public class SwitchCase : Node{
  4217. public Block Body;
  4218. public Expression Label;
  4219. public SwitchCase()
  4220. : base(NodeType.SwitchCase){
  4221. }
  4222. public SwitchCase(Expression label, Block body)
  4223. : base(NodeType.SwitchCase){
  4224. this.Body = body;
  4225. this.Label = label;
  4226. }
  4227. }
  4228. public class GotoCase : Statement{
  4229. public Expression CaseLabel;
  4230. public GotoCase(Expression caseLabel)
  4231. : base(NodeType.GotoCase){
  4232. this.CaseLabel = caseLabel;
  4233. }
  4234. }
  4235. #endif
  4236. public class SwitchInstruction : Statement{
  4237. private Expression expression;
  4238. private BlockList targets;
  4239. public SwitchInstruction()
  4240. : base(NodeType.SwitchInstruction){
  4241. }
  4242. public SwitchInstruction(Expression expression, BlockList targets)
  4243. : base(NodeType.SwitchInstruction){
  4244. this.expression = expression;
  4245. this.targets = targets;
  4246. }
  4247. public Expression Expression{
  4248. get{return this.expression;}
  4249. set{this.expression = value;}
  4250. }
  4251. public BlockList Targets{
  4252. get{return this.targets;}
  4253. set{this.targets = value;}
  4254. }
  4255. }
  4256. #if !MinimalReader
  4257. public class Typeswitch : Statement{
  4258. public TypeswitchCaseList Cases;
  4259. public Expression Expression;
  4260. public Typeswitch()
  4261. : base(NodeType.Typeswitch){
  4262. }
  4263. public Typeswitch(Expression expression, TypeswitchCaseList cases)
  4264. : base(NodeType.Typeswitch){
  4265. this.Cases = cases;
  4266. this.Expression = expression;
  4267. }
  4268. }
  4269. public class TypeswitchCase : Node{
  4270. public Block Body;
  4271. public TypeNode LabelType;
  4272. public TypeNode LabelTypeExpression;
  4273. public Expression LabelVariable;
  4274. public TypeswitchCase()
  4275. : base(NodeType.TypeswitchCase){
  4276. }
  4277. public TypeswitchCase(TypeNode labelType, Expression labelVariable, Block body)
  4278. : base(NodeType.TypeswitchCase){
  4279. this.Body = body;
  4280. this.LabelType = labelType;
  4281. this.LabelVariable = labelVariable;
  4282. }
  4283. }
  4284. public class While : Statement{
  4285. public Expression Condition;
  4286. public ExpressionList Invariants;
  4287. public Block Body;
  4288. public While()
  4289. : base(NodeType.While){
  4290. }
  4291. public While(Expression condition, Block body)
  4292. : base(NodeType.While){
  4293. this.Condition = condition;
  4294. this.Body = body;
  4295. }
  4296. }
  4297. public class DoWhile : Statement{
  4298. public Expression Condition;
  4299. public ExpressionList Invariants;
  4300. public Block Body;
  4301. public DoWhile()
  4302. : base(NodeType.DoWhile){
  4303. }
  4304. public DoWhile(Expression condition, Block body)
  4305. : base(NodeType.DoWhile){
  4306. this.Condition = condition;
  4307. this.Body = body;
  4308. }
  4309. }
  4310. public class Repeat : Statement{
  4311. public Expression Condition;
  4312. public Block Body;
  4313. public Repeat()
  4314. : base(NodeType.Repeat){
  4315. }
  4316. public Repeat(Expression condition, Block body)
  4317. : base(NodeType.Repeat){
  4318. this.Condition = condition;
  4319. this.Body = body;
  4320. }
  4321. }
  4322. public class Fixed : Statement{
  4323. public Statement Declarators;
  4324. public Block Body;
  4325. public BlockScope ScopeForTemporaryVariables;
  4326. public Fixed()
  4327. : base(NodeType.Fixed){
  4328. }
  4329. }
  4330. public class Lock : Statement{
  4331. public Expression Guard;
  4332. public Block Body;
  4333. public BlockScope ScopeForTemporaryVariable;
  4334. public Lock()
  4335. : base(NodeType.Lock){
  4336. }
  4337. }
  4338. public class ResourceUse : Statement{
  4339. public Statement ResourceAcquisition;
  4340. public Block Body;
  4341. public BlockScope ScopeForTemporaryVariable;
  4342. public ResourceUse()
  4343. : base(NodeType.ResourceUse){
  4344. }
  4345. }
  4346. public class Goto : Statement{
  4347. public Identifier TargetLabel;
  4348. public Goto()
  4349. : base(NodeType.Goto){
  4350. }
  4351. public Goto(Identifier targetLabel)
  4352. : base(NodeType.Goto){
  4353. this.TargetLabel = targetLabel;
  4354. }
  4355. }
  4356. public class VariableDeclaration : Statement{
  4357. public Expression Initializer;
  4358. public Identifier Name;
  4359. public TypeNode Type;
  4360. public TypeNode TypeExpression;
  4361. public Field Field;
  4362. public VariableDeclaration()
  4363. : base(NodeType.VariableDeclaration){
  4364. }
  4365. public VariableDeclaration(Identifier name, TypeNode type, Expression initializer)
  4366. : base(NodeType.VariableDeclaration){
  4367. this.Initializer = initializer;
  4368. this.Name = name;
  4369. this.Type = type;
  4370. }
  4371. }
  4372. public class LocalDeclaration : Node{
  4373. public Field Field;
  4374. public Identifier Name;
  4375. public Expression InitialValue;
  4376. /// <summary>
  4377. /// Used when converting a declaration with initializer into an assignment statement.
  4378. /// Usually Nop, but could be set to CopyReference to avoid dereferencing on either side.
  4379. /// </summary>
  4380. public NodeType AssignmentNodeType = NodeType.Nop;
  4381. public LocalDeclaration()
  4382. : base(NodeType.LocalDeclaration){
  4383. }
  4384. public LocalDeclaration(Identifier name, Expression initialValue)
  4385. : base(NodeType.LocalDeclaration){
  4386. this.Name = name;
  4387. this.InitialValue = initialValue;
  4388. }
  4389. public LocalDeclaration(Identifier name, Expression initialValue, NodeType assignmentNodeType)
  4390. : base(NodeType.LocalDeclaration){
  4391. this.Name = name;
  4392. this.InitialValue = initialValue;
  4393. this.AssignmentNodeType = assignmentNodeType;
  4394. }
  4395. }
  4396. public class LocalDeclarationsStatement : Statement{
  4397. public bool Constant;
  4398. public bool InitOnly;
  4399. public TypeNode Type;
  4400. public TypeNode TypeExpression;
  4401. public LocalDeclarationList Declarations;
  4402. public LocalDeclarationsStatement()
  4403. : base(NodeType.LocalDeclarationsStatement){
  4404. }
  4405. public LocalDeclarationsStatement(LocalDeclaration ldecl, TypeNode type)
  4406. : base(NodeType.LocalDeclarationsStatement){
  4407. Declarations = new LocalDeclarationList();
  4408. Declarations.Add(ldecl);
  4409. this.Type = type;
  4410. }
  4411. }
  4412. public class StatementSnippet : Statement{
  4413. public IParserFactory ParserFactory;
  4414. public StatementSnippet()
  4415. : base(NodeType.StatementSnippet){
  4416. }
  4417. public StatementSnippet(IParserFactory parserFactory, SourceContext sctx)
  4418. : base(NodeType.StatementSnippet){
  4419. this.ParserFactory = parserFactory;
  4420. this.SourceContext = sctx;
  4421. }
  4422. }
  4423. /// <summary>
  4424. /// Associates an identifier with a type or a namespace or a Uri or a list of assemblies.
  4425. /// In C# alias identifiers are used as root identifiers in qualified expressions, or as identifier prefixes.
  4426. /// </summary>
  4427. public class AliasDefinition : Node{
  4428. /// <summary>The identifier that serves as an alias for the type, namespace, Uri or list of assemblies.</summary>
  4429. public Identifier Alias;
  4430. /// <summary>The list of assemblies being aliased.</summary>
  4431. public AssemblyReferenceList AliasedAssemblies;
  4432. /// <summary>The expression that was (or should be) resolved into a type, namespace or Uri.</summary>
  4433. public Expression AliasedExpression;
  4434. /// <summary>The namespace being aliased.</summary>
  4435. public Identifier AliasedNamespace;
  4436. /// <summary>A reference to the type being aliased.</summary>
  4437. public TypeReference AliasedType;
  4438. /// <summary>The Uri being aliased.</summary>
  4439. public Identifier AliasedUri;
  4440. /// <summary>
  4441. /// If an alias definition conflicts with a type definition and this causes an ambiguity, the conflicting type is stored here
  4442. /// by the code that detects the ambiguity. A later visitor is expected to report an error if this is not null.
  4443. /// </summary>
  4444. public TypeNode ConflictingType;
  4445. public bool RestrictToInterfaces;
  4446. public bool RestrictToClassesAndInterfaces;
  4447. public AliasDefinition()
  4448. : base(NodeType.AliasDefinition){
  4449. }
  4450. public AliasDefinition(Identifier alias, Expression aliasedExpression)
  4451. : base(NodeType.AliasDefinition){
  4452. this.Alias = alias;
  4453. this.AliasedExpression = aliasedExpression;
  4454. }
  4455. public AliasDefinition(Identifier alias, Expression aliasedExpression, SourceContext sctx)
  4456. : base(NodeType.AliasDefinition){
  4457. this.Alias = alias;
  4458. this.AliasedExpression = aliasedExpression;
  4459. this.SourceContext = sctx;
  4460. }
  4461. }
  4462. public class UsedNamespace : Node{
  4463. public Identifier Namespace;
  4464. public Identifier URI;
  4465. public UsedNamespace()
  4466. : base(NodeType.UsedNamespace){
  4467. }
  4468. public UsedNamespace(Identifier Namespace)
  4469. : base(NodeType.UsedNamespace){
  4470. this.Namespace = Namespace;
  4471. }
  4472. public UsedNamespace(Identifier Namespace, SourceContext sctx)
  4473. : base(NodeType.UsedNamespace){
  4474. this.Namespace = Namespace;
  4475. this.SourceContext = sctx;
  4476. }
  4477. }
  4478. #endif
  4479. #if !FxCop
  4480. public class ExceptionHandler : Node{
  4481. private NodeType handlerType;
  4482. private Block tryStartBlock;
  4483. private Block blockAfterTryEnd;
  4484. private Block handlerStartBlock;
  4485. private Block blockAfterHandlerEnd;
  4486. private Block filterExpression;
  4487. private TypeNode filterType;
  4488. public ExceptionHandler()
  4489. : base(NodeType.ExceptionHandler){
  4490. }
  4491. public NodeType HandlerType{
  4492. get{return this.handlerType;}
  4493. set{this.handlerType = value;}
  4494. }
  4495. public Block TryStartBlock{
  4496. get{return this.tryStartBlock;}
  4497. set{this.tryStartBlock = value;}
  4498. }
  4499. public Block BlockAfterTryEnd{
  4500. get{return this.blockAfterTryEnd;}
  4501. set{this.blockAfterTryEnd = value;}
  4502. }
  4503. public Block HandlerStartBlock{
  4504. get{return this.handlerStartBlock;}
  4505. set{this.handlerStartBlock = value;}
  4506. }
  4507. public Block BlockAfterHandlerEnd{
  4508. get{return this.blockAfterHandlerEnd;}
  4509. set{this.blockAfterHandlerEnd = value;}
  4510. }
  4511. public Block FilterExpression{
  4512. get{return this.filterExpression;}
  4513. set{this.filterExpression = value;}
  4514. }
  4515. public TypeNode FilterType{
  4516. get{return this.filterType;}
  4517. set{this.filterType = value;}
  4518. }
  4519. }
  4520. #endif
  4521. public class AttributeNode : Node{
  4522. #if !MinimalReader
  4523. public bool IsPseudoAttribute;
  4524. #endif
  4525. public AttributeNode()
  4526. : base(NodeType.Attribute){
  4527. }
  4528. public AttributeNode(Expression constructor, ExpressionList expressions)
  4529. : base(NodeType.Attribute){
  4530. this.constructor = constructor;
  4531. this.expressions = expressions;
  4532. this.target = AttributeTargets.All;
  4533. }
  4534. #if !MinimalReader
  4535. public AttributeNode(Expression constructor, ExpressionList expressions, AttributeTargets target)
  4536. : base(NodeType.Attribute){
  4537. this.constructor = constructor;
  4538. this.expressions = expressions;
  4539. this.target = target;
  4540. }
  4541. #endif
  4542. private Expression constructor;
  4543. public Expression Constructor{
  4544. get{return this.constructor;}
  4545. set{this.constructor = value;}
  4546. }
  4547. private ExpressionList expressions;
  4548. /// <summary>
  4549. /// Invariant: positional arguments occur first and in order in the expression list. Named arguments
  4550. /// follow posititional arguments in any order.
  4551. /// </summary>
  4552. public ExpressionList Expressions{
  4553. get{return this.expressions;}
  4554. set{this.expressions = value;}
  4555. }
  4556. private AttributeTargets target;
  4557. public AttributeTargets Target{
  4558. get{return this.target;}
  4559. set{this.target = value;}
  4560. }
  4561. private bool allowMultiple;
  4562. public virtual bool AllowMultiple{
  4563. get{
  4564. if (this.usageAttribute == null) this.GetUsageInformation();
  4565. return this.allowMultiple;
  4566. }
  4567. set{
  4568. this.allowMultiple = value;
  4569. }
  4570. }
  4571. private bool inherited;
  4572. public virtual bool Inherited{
  4573. get{
  4574. if (this.usageAttribute == null) this.GetUsageInformation();
  4575. return this.inherited;
  4576. }
  4577. set{
  4578. this.inherited = value;
  4579. }
  4580. }
  4581. private AttributeTargets validOn;
  4582. public virtual AttributeTargets ValidOn{
  4583. get{
  4584. if (this.usageAttribute == null) this.GetUsageInformation();
  4585. return this.validOn;
  4586. }
  4587. set{
  4588. this.validOn = value;
  4589. }
  4590. }
  4591. private TypeNode type;
  4592. public virtual TypeNode Type{
  4593. get{
  4594. if (this.type == null){
  4595. MemberBinding mb = this.Constructor as MemberBinding;
  4596. Member cons = mb == null ? null : mb.BoundMember;
  4597. this.type = cons == null ? null : cons.DeclaringType;
  4598. }
  4599. return this.type;
  4600. }
  4601. set{
  4602. this.type = value;
  4603. }
  4604. }
  4605. private AttributeNode usageAttribute;
  4606. private void GetUsageInformation(){
  4607. AttributeNode attr = null;
  4608. TypeNode attrType = this.Type;
  4609. while (attrType != null){
  4610. attr = attrType.GetAttribute(SystemTypes.AttributeUsageAttribute);
  4611. if (attr != null) break;
  4612. attrType = attrType.BaseType;
  4613. }
  4614. if (attr == null){
  4615. this.usageAttribute = AttributeNode.DoesNotExist;
  4616. return;
  4617. }
  4618. ExpressionList args = attr.Expressions;
  4619. if (args == null || args.Count < 1) return;
  4620. Literal lit = args[0] as Literal;
  4621. if (lit == null || !(lit.Value is int)) {
  4622. #if ExtendedRuntime
  4623. MemberBinding mb = args[0] as MemberBinding;
  4624. if (mb != null) {
  4625. Field f = mb.BoundMember as Field;
  4626. if (f != null && f.IsLiteral) {
  4627. lit = f.Initializer as Literal;
  4628. }
  4629. }
  4630. if (lit == null || !(lit.Value is int))
  4631. #endif
  4632. return;
  4633. }
  4634. //^ assert lit.Value != null;
  4635. this.validOn = (AttributeTargets)(int)lit.Value;
  4636. for (int i = 1, n = args.Count; i < n; i++){
  4637. NamedArgument narg = args[i] as NamedArgument;
  4638. if (narg == null || narg.Name == null) continue;
  4639. lit = narg.Value as Literal;
  4640. if (lit == null) continue;
  4641. if (narg.Name.UniqueIdKey == StandardIds.AllowMultiple.UniqueIdKey){
  4642. if (lit.Value == null || !(lit.Value is bool)) continue;
  4643. this.allowMultiple = (bool)lit.Value;
  4644. }else if (narg.Name.UniqueIdKey == StandardIds.Inherited.UniqueIdKey){
  4645. if (lit.Value == null || !(lit.Value is bool)) continue;
  4646. this.inherited = (bool)lit.Value;
  4647. }
  4648. }
  4649. }
  4650. public static readonly AttributeNode DoesNotExist = new AttributeNode();
  4651. #if !NoReflection
  4652. public virtual System.Attribute GetRuntimeAttribute(){
  4653. MemberBinding mb = this.Constructor as MemberBinding;
  4654. if (mb == null) return null;
  4655. InstanceInitializer constr = mb.BoundMember as InstanceInitializer;
  4656. if (constr == null) return null;
  4657. ParameterList parameters = constr.Parameters;
  4658. int paramCount = parameters == null ? 0 : parameters.Count;
  4659. object[] argumentValues = new object[paramCount];
  4660. ExpressionList argumentExpressions = this.Expressions;
  4661. int exprCount = argumentExpressions == null ? 0 : argumentExpressions.Count;
  4662. for (int i = 0, j = 0; i < paramCount; i++){
  4663. if (j >= exprCount) return null;
  4664. //^ assert argumentExpressions != null;
  4665. Expression argExpr = argumentExpressions[j++];
  4666. Literal lit = argExpr as Literal;
  4667. if (lit == null) continue;
  4668. argumentValues[i] = this.GetCoercedLiteralValue(lit.Type, lit.Value);
  4669. }
  4670. System.Attribute attr = this.ConstructAttribute(constr, argumentValues);
  4671. if (attr == null) return null;
  4672. for (int i = 0; i < exprCount; i++){
  4673. //^ assert argumentExpressions != null;
  4674. NamedArgument namedArg = argumentExpressions[i] as NamedArgument;
  4675. if (namedArg == null) continue;
  4676. if (namedArg.Name == null) continue;
  4677. Literal lit = namedArg.Value as Literal;
  4678. if (lit == null) continue;
  4679. object val = this.GetCoercedLiteralValue(lit.Type, lit.Value);
  4680. if (namedArg.IsCustomAttributeProperty){
  4681. TypeNode t = constr.DeclaringType;
  4682. while (t != null){
  4683. Property prop = t.GetProperty(namedArg.Name);
  4684. if (prop != null){
  4685. this.SetAttributeProperty(prop, attr, val);
  4686. t = null;
  4687. }else
  4688. t = t.BaseType;
  4689. }
  4690. }else{
  4691. TypeNode t = constr.DeclaringType;
  4692. while (t != null){
  4693. Field f = constr.DeclaringType.GetField(namedArg.Name);
  4694. if (f != null){
  4695. System.Reflection.FieldInfo fieldInfo = f.GetFieldInfo();
  4696. if (fieldInfo != null) fieldInfo.SetValue(attr, val);
  4697. t = null;
  4698. }else
  4699. t = t.BaseType;
  4700. }
  4701. }
  4702. }
  4703. return attr;
  4704. }
  4705. /// <summary>
  4706. /// Gets the value of the literal coercing literals of TypeNode, EnumNode, TypeNode[], and EnumNode[] as needed.
  4707. /// </summary>
  4708. /// <param name="type">A TypeNode representing the type of the literal</param>
  4709. /// <param name="value">The value of the literal</param>
  4710. /// <returns>An object that has been coerced to the appropiate runtime type</returns>
  4711. protected object GetCoercedLiteralValue(TypeNode type, object value){
  4712. if (type == null || value == null) return null;
  4713. switch (type.typeCode) {
  4714. case ElementType.Class:
  4715. return ((TypeNode)value).GetRuntimeType();
  4716. case ElementType.ValueType:
  4717. return System.Enum.ToObject(type.GetRuntimeType(), value);
  4718. case ElementType.SzArray:
  4719. return this.GetCoercedArrayLiteral((ArrayType)type, (Array)value);
  4720. default:
  4721. Literal lit = value as Literal;
  4722. if (lit != null && type == CoreSystemTypes.Object && lit.Type is EnumNode)
  4723. return this.GetCoercedLiteralValue(lit.Type, lit.Value);
  4724. break;
  4725. }
  4726. return value;
  4727. }
  4728. /// <summary>
  4729. /// Gets the array literal in arrayValue coercing TypeNode[] and EnumNode[] as needed.
  4730. /// </summary>
  4731. /// <param name="arrayType">A TypeNode representing the array type</param>
  4732. /// <param name="arrayValue">The value of the array literal to coerce</param>
  4733. /// <returns>An Array object that has been coerced to the appropriate runtime type</returns>
  4734. protected Array GetCoercedArrayLiteral(ArrayType arrayType, Array arrayValue){
  4735. if (arrayType == null) return null;
  4736. if (arrayValue == null) return null;
  4737. // Multi-dimensional arrays are not legal in attribute instances according section 17.1.3 of the C# 1.0 spec
  4738. if (arrayValue.Rank != 1) return null;
  4739. TypeNode elemType = arrayType.ElementType;
  4740. if (elemType.typeCode != ElementType.ValueType && elemType.typeCode != ElementType.Class)
  4741. return arrayValue;
  4742. int arraySize = arrayValue.GetLength(0);
  4743. Type et = elemType.GetRuntimeType();
  4744. if (et == null) return null;
  4745. Array val = Array.CreateInstance(et, arraySize);
  4746. for (int i = 0; i < arraySize; i++)
  4747. val.SetValue(this.GetCoercedLiteralValue(elemType, arrayValue.GetValue(i)), i);
  4748. return val;
  4749. }
  4750. private void SetAttributeProperty(Property/*!*/ prop, System.Attribute attr, object val) {
  4751. //This could execute partially trusted code, so set up a very restrictive execution environment
  4752. //TODO: skip this if the attribute is from a trusted assembly
  4753. System.Reflection.PropertyInfo propInfo = prop.GetPropertyInfo();
  4754. if (propInfo == null) return;
  4755. //Because we invoke the setter through reflection, a stack walk is performed. The following two commented-out statements
  4756. //would cause the stack walk to fail.
  4757. //For now, we will run the setter in full trust until we work around this.
  4758. //For VS2005 and later, we will construct a DynamicMethod, wrap it in a delegate, and invoke that.
  4759. //System.Security.PermissionSet perm = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None);
  4760. //perm.PermitOnly();
  4761. try{
  4762. propInfo.SetValue(attr, val, null);
  4763. }catch{}
  4764. }
  4765. private System.Attribute ConstructAttribute(InstanceInitializer/*!*/ constr, object[] argumentValues){
  4766. //This could execute partially trusted code, so set up a very restrictive execution environment
  4767. //TODO: skip this if the attribute is from a trusted assembly
  4768. System.Reflection.ConstructorInfo consInfo = constr.GetConstructorInfo();
  4769. if (consInfo == null) return null;
  4770. //Because we invoke the constructor through reflection, a stack walk is performed. The following two commented-out statements
  4771. //would cause the stack walk to fail.
  4772. //For VS2003 and earlier, we will run the constructor in full trust.
  4773. //For VS2005 and later, we will construct a DynamicMethod, wrap it in a delegate, and invoke that.
  4774. //System.Security.PermissionSet perm = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None);
  4775. //perm.PermitOnly();
  4776. try{
  4777. return consInfo.Invoke(argumentValues) as System.Attribute;
  4778. }catch{}
  4779. return null;
  4780. }
  4781. #endif
  4782. public Expression GetPositionalArgument(int position){
  4783. if (this.Expressions == null || this.Expressions.Count <= position) return null;
  4784. Expression e = this.Expressions[position];
  4785. NamedArgument na = e as NamedArgument;
  4786. if (na != null) return null;
  4787. return e;
  4788. }
  4789. public Expression GetNamedArgument(Identifier name) {
  4790. if (name == null || this.Expressions == null) return null;
  4791. foreach (Expression e in this.Expressions) {
  4792. NamedArgument na = e as NamedArgument;
  4793. if (na == null) continue;
  4794. if (na.Name == null) continue;
  4795. if (na.Name.UniqueIdKey == name.UniqueIdKey) return na.Value;
  4796. }
  4797. return null;
  4798. }
  4799. }
  4800. public class SecurityAttribute : Node{
  4801. public SecurityAttribute()
  4802. : base(NodeType.SecurityAttribute){
  4803. }
  4804. private System.Security.Permissions.SecurityAction action;
  4805. public System.Security.Permissions.SecurityAction Action{
  4806. get{return this.action;}
  4807. set{this.action = value;}
  4808. }
  4809. private AttributeList permissionAttributes;
  4810. public AttributeList PermissionAttributes{
  4811. get{return this.permissionAttributes;}
  4812. set{this.permissionAttributes = value;}
  4813. }
  4814. protected string serializedPermissions;
  4815. public string SerializedPermissions{
  4816. get{
  4817. #if !NoReflection || FxCop
  4818. if (this.serializedPermissions == null && this.PermissionAttributes != null){
  4819. lock (this){
  4820. if (this.serializedPermissions != null) return this.serializedPermissions;
  4821. System.Security.PermissionSet permissions = this.Permissions;
  4822. if (permissions == null) return null;
  4823. System.Security.SecurityElement xml = permissions.ToXml();
  4824. if (xml == null) return null;
  4825. this.serializedPermissions = xml.ToString();
  4826. //TODO: if the target platform is different from the host platform, replace references to host platform
  4827. //assemblies with references to target platform assemblies
  4828. }
  4829. }
  4830. #endif
  4831. return this.serializedPermissions;
  4832. }
  4833. set{
  4834. this.serializedPermissions = value;
  4835. }
  4836. }
  4837. #if !NoReflection || FxCop
  4838. protected System.Security.PermissionSet permissions;
  4839. public System.Security.PermissionSet Permissions{
  4840. get{
  4841. if (this.permissions == null){
  4842. lock (this){
  4843. if (this.permissions != null) return this.permissions;
  4844. System.Security.PermissionSet permissions = null;
  4845. #if !FxCop
  4846. if (this.PermissionAttributes != null){
  4847. permissions = this.InstantiatePermissionAttributes();
  4848. }else if (this.serializedPermissions != null){
  4849. permissions = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None);
  4850. permissions.FromXml(this.GetSecurityElement());
  4851. }
  4852. #elif !TestBuild
  4853. permissions = PermissionsHelper.GetPermissions(this);
  4854. #endif
  4855. this.permissions = permissions;
  4856. }
  4857. }
  4858. return this.permissions;
  4859. }
  4860. set{
  4861. this.permissions = value;
  4862. }
  4863. }
  4864. #endif
  4865. #if !NoReflection
  4866. protected System.Security.SecurityElement GetSecurityElement(){
  4867. #if WHIDBEY
  4868. return System.Security.SecurityElement.FromString(this.serializedPermissions);
  4869. #else
  4870. System.Reflection.Assembly mscorlib = CoreSystemTypes.SystemAssembly.GetRuntimeAssembly();
  4871. if (mscorlib == null) { Debug.Fail(""); return null; }
  4872. Type parserType = mscorlib.GetType("System.Security.Util.Parser", true, false);
  4873. if (parserType == null) { Debug.Fail(""); return null; }
  4874. System.Reflection.MethodInfo getTopElement = parserType.GetMethod("GetTopElement", BindingFlags.NonPublic|BindingFlags.Instance, null, new Type[]{}, null);
  4875. if (getTopElement == null) { Debug.Fail(""); return null; }
  4876. object parser = Activator.CreateInstance(parserType, BindingFlags.Instance|BindingFlags.NonPublic, null, new Object[]{this.serializedPermissions}, null);
  4877. return (System.Security.SecurityElement)getTopElement.Invoke(parser, null);
  4878. #endif
  4879. }
  4880. protected System.Security.PermissionSet InstantiatePermissionAttributes(){
  4881. System.Security.PermissionSet permissions = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None);
  4882. AttributeList permissionAttributes = this.PermissionAttributes;
  4883. for (int i = 0, n = permissionAttributes == null ? 0 : permissionAttributes.Count; i < n; i++){
  4884. //^ assert permissionAttributes != null;
  4885. object result = this.GetPermissionOrSetOfPermissionsFromAttribute(permissionAttributes[i]);
  4886. if (result == null) continue;
  4887. if (result is System.Security.PermissionSet)
  4888. permissions = permissions.Union((System.Security.PermissionSet)result);
  4889. else{
  4890. System.Security.IPermission permission = result as System.Security.IPermission;
  4891. if (permission == null) continue;
  4892. permissions.AddPermission(permission);
  4893. }
  4894. }
  4895. return permissions;
  4896. }
  4897. protected object GetPermissionOrSetOfPermissionsFromAttribute(AttributeNode attr){
  4898. if (attr == null) return null;
  4899. System.Security.Permissions.SecurityAttribute secAttr = attr.GetRuntimeAttribute() as System.Security.Permissions.SecurityAttribute;
  4900. if (secAttr == null) return null;
  4901. System.Security.Permissions.PermissionSetAttribute pSetAttr = secAttr as System.Security.Permissions.PermissionSetAttribute;
  4902. if (pSetAttr != null)
  4903. return pSetAttr.CreatePermissionSet();
  4904. else
  4905. return this.CreatePermission(secAttr);
  4906. }
  4907. private System.Security.IPermission CreatePermission(System.Security.Permissions.SecurityAttribute/*!*/ secAttr) {
  4908. //This could execute partially trusted code, so set up a very restrictive execution environment
  4909. System.Security.PermissionSet perm = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None);
  4910. //TODO: add permissions if the attribute is from a trusted assembly
  4911. perm.PermitOnly();
  4912. try{
  4913. return secAttr.CreatePermission();
  4914. }catch{}
  4915. return null;
  4916. }
  4917. #endif
  4918. }
  4919. public struct Resource{
  4920. private bool isPublic;
  4921. private string name;
  4922. private Module definingModule;
  4923. private byte[] data;
  4924. public bool IsPublic{
  4925. get{return this.isPublic;}
  4926. set{this.isPublic = value;}
  4927. }
  4928. public string Name{
  4929. get{return this.name;}
  4930. set{this.name = value;}
  4931. }
  4932. public Module DefiningModule{
  4933. get{return this.definingModule;}
  4934. set{this.definingModule = value;}
  4935. }
  4936. public byte[] Data{
  4937. get{return this.data;}
  4938. set{this.data = value;}
  4939. }
  4940. }
  4941. public struct Win32Resource{
  4942. private string typeName;
  4943. private int typeId;
  4944. private string name;
  4945. private int id;
  4946. private int languageId;
  4947. private int codePage;
  4948. private byte[] data;
  4949. public string TypeName {
  4950. get{return this.typeName;}
  4951. set{this.typeName = value;}
  4952. }
  4953. public int TypeId{
  4954. get{return this.typeId;}
  4955. set{this.typeId = value;}
  4956. }
  4957. public string Name{
  4958. get{return this.name;}
  4959. set{this.name = value;}
  4960. }
  4961. public int Id{
  4962. get{return this.id;}
  4963. set{this.id = value;}
  4964. }
  4965. public int LanguageId{
  4966. get{return this.languageId;}
  4967. set{this.languageId = value;}
  4968. }
  4969. public int CodePage{
  4970. get{return this.codePage;}
  4971. set{this.codePage = value;}
  4972. }
  4973. public byte[] Data{
  4974. get{return this.data;}
  4975. set{this.data = value;}
  4976. }
  4977. }
  4978. #if FxCop
  4979. public class ModuleNode : Node, IDisposable{
  4980. #else
  4981. public class Module : Node, IDisposable{
  4982. #endif
  4983. internal Reader reader;
  4984. public delegate void TypeNodeListProvider(Module/*!*/ module);
  4985. protected TypeNodeListProvider provideTypeNodeList;
  4986. public delegate TypeNode TypeNodeProvider(Identifier/*!*/ @namespace, Identifier/*!*/ name);
  4987. protected TypeNodeProvider provideTypeNode;
  4988. protected TrivialHashtable namespaceTable = new TrivialHashtable();
  4989. protected NamespaceList namespaceList;
  4990. protected int savedTypesLength;
  4991. public delegate void CustomAttributeProvider(Module/*!*/ module);
  4992. protected CustomAttributeProvider provideCustomAttributes;
  4993. public delegate void ResourceProvider(Module/*!*/ module);
  4994. protected ResourceProvider provideResources;
  4995. public delegate AssemblyNode AssemblyReferenceResolver(AssemblyReference/*!*/ assemblyReference, Module/*!*/ referencingModule);
  4996. public event AssemblyReferenceResolver AssemblyReferenceResolution;
  4997. public event AssemblyReferenceResolver AssemblyReferenceResolutionAfterProbingFailed;
  4998. #if !NoXml
  4999. public delegate XmlDocument DocumentationResolver(Module referencingModule);
  5000. public event DocumentationResolver DocumentationResolution = null;
  5001. #endif
  5002. #if !MinimalReader
  5003. public bool IsNormalized;
  5004. #endif
  5005. #if !NoWriter
  5006. public bool UsePublicKeyTokensForAssemblyReferences = true;
  5007. #endif
  5008. internal int FileAlignment = 512;
  5009. internal readonly static object GlobalLock = new object();
  5010. #if !NoWriter
  5011. public bool StripOptionalModifiersFromLocals = true;
  5012. #endif
  5013. #if FxCop
  5014. public ModuleNode()
  5015. #else
  5016. public Module()
  5017. #endif
  5018. : base(NodeType.Module){
  5019. #if !MinimalReader
  5020. this.IsNormalized = false;
  5021. #endif
  5022. }
  5023. #if FxCop
  5024. public ModuleNode(TypeNodeProvider provider, TypeNodeListProvider listProvider, CustomAttributeProvider provideCustomAttributes, ResourceProvider provideResources)
  5025. #else
  5026. public Module(TypeNodeProvider provider, TypeNodeListProvider listProvider, CustomAttributeProvider provideCustomAttributes, ResourceProvider provideResources)
  5027. #endif
  5028. : base(NodeType.Module){
  5029. this.provideCustomAttributes = provideCustomAttributes;
  5030. this.provideResources = provideResources;
  5031. this.provideTypeNode = provider;
  5032. this.provideTypeNodeList = listProvider;
  5033. #if !MinimalReader
  5034. this.IsNormalized = true;
  5035. #endif
  5036. }
  5037. public virtual void Dispose(){
  5038. if (this.reader != null) this.reader.Dispose();
  5039. this.reader = null;
  5040. ModuleReferenceList mrefs = this.moduleReferences;
  5041. for (int i = 0, n = mrefs == null ? 0 : mrefs.Count; i < n; i++){
  5042. //^ assert mrefs != null;
  5043. ModuleReference mr = mrefs[i];
  5044. if (mr != null && mr.Module == null) continue;
  5045. mr.Module.Dispose();
  5046. }
  5047. this.moduleReferences = null;
  5048. }
  5049. private AssemblyReferenceList assemblyReferences;
  5050. public AssemblyReferenceList AssemblyReferences{
  5051. get{return this.assemblyReferences;}
  5052. set{this.assemblyReferences = value;}
  5053. }
  5054. private AssemblyNode containingAssembly;
  5055. /// <summary>The assembly, if any, that includes this module in its ModuleReferences.</summary>
  5056. public AssemblyNode ContainingAssembly{
  5057. get{return this.containingAssembly;}
  5058. set{this.containingAssembly = value;}
  5059. }
  5060. private ushort dllCharacteristics;
  5061. public ushort DllCharacteristics {
  5062. get { return this.dllCharacteristics; }
  5063. set { this.dllCharacteristics = value; }
  5064. }
  5065. private string directory;
  5066. public string Directory{
  5067. get{return this.directory;}
  5068. set{this.directory = value;}
  5069. }
  5070. private AssemblyHashAlgorithm hashAlgorithm = AssemblyHashAlgorithm.SHA1;
  5071. public AssemblyHashAlgorithm HashAlgorithm{
  5072. get{return this.hashAlgorithm;}
  5073. set{this.hashAlgorithm = value;}
  5074. }
  5075. private byte[] hashValue;
  5076. public byte[] HashValue{
  5077. get{return this.hashValue;}
  5078. set{this.hashValue = value;}
  5079. }
  5080. private ModuleKindFlags kind;
  5081. /// <summary>An enumeration that indicates if the module is an executable, library or resource, and so on.</summary>
  5082. public ModuleKindFlags Kind{
  5083. get{return this.kind;}
  5084. set{this.kind = value;}
  5085. }
  5086. private string location;
  5087. /// <summary>The path of the file from which this module or assembly was loaded or will be stored in.</summary>
  5088. public string Location{
  5089. get{return this.location;}
  5090. set{this.location = value;}
  5091. }
  5092. private System.Guid mvid;
  5093. public System.Guid Mvid{
  5094. get{return this.mvid;}
  5095. set{this.mvid = value;}
  5096. }
  5097. private string targetRuntimeVersion;
  5098. /// <summary>Identifies the version of the CLR that is required to load this module or assembly.</summary>
  5099. public string TargetRuntimeVersion{
  5100. get{return this.targetRuntimeVersion;}
  5101. set{this.targetRuntimeVersion = value;}
  5102. }
  5103. private int linkerMajorVersion = 6;
  5104. public int LinkerMajorVersion{
  5105. get{return this.linkerMajorVersion;}
  5106. set{this.linkerMajorVersion = value;}
  5107. }
  5108. private int linkerMinorVersion;
  5109. public int LinkerMinorVersion{
  5110. get{return this.linkerMinorVersion;}
  5111. set{this.linkerMinorVersion = value;}
  5112. }
  5113. private int metadataFormatMajorVersion;
  5114. public int MetadataFormatMajorVersion{
  5115. get{return this.metadataFormatMajorVersion;}
  5116. set{this.metadataFormatMajorVersion = value;}
  5117. }
  5118. private int metadataFormatMinorVersion;
  5119. public int MetadataFormatMinorVersion{
  5120. get{return this.metadataFormatMinorVersion;}
  5121. set{this.metadataFormatMinorVersion = value;}
  5122. }
  5123. private string name;
  5124. /// <summary>The name of the module or assembly. Includes the file extension if the module is not an assembly.</summary>
  5125. public string Name{
  5126. get{return this.name;}
  5127. set{this.name = value;}
  5128. }
  5129. private PEKindFlags peKind = PEKindFlags.ILonly;
  5130. public PEKindFlags PEKind{
  5131. get{return this.peKind;}
  5132. set{this.peKind = value;}
  5133. }
  5134. private bool trackDebugData;
  5135. public bool TrackDebugData{
  5136. get{return this.trackDebugData;}
  5137. set{this.trackDebugData = value;}
  5138. }
  5139. #if !FxCop
  5140. private ArrayList metadataImportErrors;
  5141. /// <summary>
  5142. /// If any exceptions were encountered while reading in this module, they are recorded here. Since reading is lazy,
  5143. /// this list can grow dynamically during the use of a module.
  5144. /// </summary>
  5145. public ArrayList MetadataImportErrors{
  5146. get{return this.metadataImportErrors;}
  5147. set{this.metadataImportErrors = value;}
  5148. }
  5149. #endif
  5150. protected AttributeList attributes;
  5151. /// <summary>
  5152. /// The attributes associated with this module or assembly. This corresponds to C# custom attributes with the assembly or module target specifier.
  5153. /// </summary>
  5154. public virtual AttributeList Attributes{
  5155. get{
  5156. if (this.attributes != null) return this.attributes;
  5157. if (this.provideCustomAttributes != null){
  5158. lock (Module.GlobalLock){
  5159. if (this.attributes == null)
  5160. this.provideCustomAttributes(this);
  5161. }
  5162. }else
  5163. this.attributes = new AttributeList();
  5164. return this.attributes;
  5165. }
  5166. set{
  5167. this.attributes = value;
  5168. }
  5169. }
  5170. protected SecurityAttributeList securityAttributes;
  5171. /// <summary>
  5172. /// Declarative security for the module or assembly.
  5173. /// </summary>
  5174. public virtual SecurityAttributeList SecurityAttributes{
  5175. get{
  5176. if (this.securityAttributes != null) return this.securityAttributes;
  5177. if (this.provideCustomAttributes != null){
  5178. AttributeList dummy = this.Attributes; //As a side effect, this.securityAttributes gets populated
  5179. if (dummy != null) dummy = null;
  5180. }else
  5181. this.securityAttributes = new SecurityAttributeList();
  5182. return this.securityAttributes;
  5183. }
  5184. set{
  5185. this.securityAttributes = value;
  5186. }
  5187. }
  5188. #if !MinimalReader
  5189. /// <summary>The source code, if any, corresponding to the value in Documentation.</summary>
  5190. public Node DocumentationNode;
  5191. #endif
  5192. #if !NoXml
  5193. protected XmlDocument documentation;
  5194. /// <summary>An XML Document Object Model for a document containing all of the documentation comments applicable to members
  5195. /// defined in this module.</summary>
  5196. public virtual XmlDocument Documentation{
  5197. get{
  5198. XmlDocument documentation = this.documentation;
  5199. if (documentation != null) return documentation;
  5200. if (this.DocumentationResolution != null)
  5201. documentation = this.documentation = this.DocumentationResolution(this);
  5202. if (documentation != null) return documentation;
  5203. XmlDocument doc = null;
  5204. if (this.Directory != null && this.Name != null){
  5205. string fileName = this.Name+".xml";
  5206. System.Globalization.CultureInfo cc = System.Globalization.CultureInfo.CurrentUICulture;
  5207. while (cc != null && cc != System.Globalization.CultureInfo.InvariantCulture) {
  5208. doc = this.ProbeForXmlDocumentation(this.Directory, cc.Name, fileName);
  5209. if (doc != null) break;
  5210. cc = cc.Parent;
  5211. }
  5212. if (doc == null)
  5213. doc = this.ProbeForXmlDocumentation(this.Directory, null, fileName);
  5214. }
  5215. if (doc == null) doc = new XmlDocument();
  5216. return this.documentation = doc;
  5217. }
  5218. set{
  5219. this.documentation = value;
  5220. }
  5221. }
  5222. public virtual XmlDocument ProbeForXmlDocumentation(string dir, string subDir, string fileName){
  5223. try{
  5224. if (dir == null || fileName == null) return null;
  5225. if (subDir != null) dir = Path.Combine(dir, subDir);
  5226. string docFileName = Path.Combine(dir, fileName);
  5227. if (File.Exists(docFileName)){
  5228. XmlDocument doc = new XmlDocument();
  5229. using (TextReader reader = File.OpenText(docFileName)){
  5230. doc.Load(reader);
  5231. return doc;
  5232. }
  5233. }
  5234. }catch(Exception e){
  5235. if (this.MetadataImportErrors == null) this.MetadataImportErrors = new ArrayList();
  5236. this.MetadataImportErrors.Add(e);
  5237. }
  5238. return null;
  5239. }
  5240. #endif
  5241. protected internal static readonly Method NoSuchMethod = new Method();
  5242. protected Method entryPoint;
  5243. /// <summary>If this module is an executable, this method is the one that gets called to start the execution of managed code.</summary>
  5244. public virtual Method EntryPoint{
  5245. get{
  5246. if (this.entryPoint == null){
  5247. if (this.provideCustomAttributes != null){
  5248. AttributeList dummy = this.Attributes; //Gets the entry point as a side effect
  5249. if (dummy != null) dummy = null;
  5250. }else
  5251. this.entryPoint = Module.NoSuchMethod;
  5252. }
  5253. if (this.entryPoint == Module.NoSuchMethod) return null;
  5254. return this.entryPoint;
  5255. }
  5256. set{
  5257. this.entryPoint = value;
  5258. }
  5259. }
  5260. protected ModuleReferenceList moduleReferences;
  5261. /// <summary>The list of modules (excluding assemblies) defining members that are referred to in this module or assembly.</summary>
  5262. public ModuleReferenceList ModuleReferences{
  5263. get{
  5264. //Populating the type list may cause module references to be added
  5265. if (this.Types == null) return this.moduleReferences;
  5266. return this.moduleReferences;
  5267. }
  5268. set{
  5269. this.moduleReferences = value;
  5270. }
  5271. }
  5272. #if !MinimalReader
  5273. public virtual bool ContainsModule(Module module) {
  5274. if (module == null || this.ModuleReferences == null || this.ModuleReferences.Count == 0) return false;
  5275. int n = this.ModuleReferences.Count;
  5276. for (int i = 0; i < n; ++i) {
  5277. ModuleReference mr = this.ModuleReferences[i];
  5278. if (mr == null) continue;
  5279. if (mr.Module == module)
  5280. return true;
  5281. }
  5282. return false;
  5283. }
  5284. #endif
  5285. protected ResourceList resources;
  5286. /// <summary>
  5287. /// A list of managed resources linked or embedded into this module or assembly.
  5288. /// </summary>
  5289. public virtual ResourceList Resources{
  5290. get{
  5291. if (this.resources != null) return this.resources;
  5292. if (this.provideResources != null){
  5293. lock (Module.GlobalLock){
  5294. if (this.resources == null)
  5295. this.provideResources(this);
  5296. }
  5297. }else
  5298. this.resources = new ResourceList();
  5299. return this.resources;
  5300. }
  5301. set{
  5302. this.resources = value;
  5303. }
  5304. }
  5305. protected Win32ResourceList win32Resources;
  5306. /// <summary>
  5307. /// A list of Win32 resources embedded in this module or assembly.
  5308. /// </summary>
  5309. public virtual Win32ResourceList Win32Resources{
  5310. get{
  5311. if (this.win32Resources != null) return this.win32Resources;
  5312. if (this.provideResources != null){
  5313. ResourceList dummy = this.Resources; //gets the win32 resources as as side effect
  5314. if (dummy != null) dummy = null;
  5315. }else
  5316. this.win32Resources = new Win32ResourceList();
  5317. return this.win32Resources;
  5318. }
  5319. set{
  5320. this.win32Resources = value;
  5321. }
  5322. }
  5323. #if !NoWriter
  5324. public virtual void AddWin32ResourceFile(string win32ResourceFilePath){
  5325. if (win32ResourceFilePath == null) return;
  5326. Writer.AddWin32ResourceFileToModule(this, win32ResourceFilePath);
  5327. }
  5328. public virtual void AddWin32ResourceFile(Stream win32ResourceStream){
  5329. if (win32ResourceStream == null) return;
  5330. Writer.AddWin32ResourceFileToModule(this, win32ResourceStream);
  5331. }
  5332. public virtual void AddWin32Icon(string win32IconFilePath){
  5333. if (win32IconFilePath == null) return;
  5334. Writer.AddWin32Icon(this, win32IconFilePath);
  5335. }
  5336. public virtual void AddWin32Icon(Stream win32IconStream){
  5337. Writer.AddWin32Icon(this, win32IconStream);
  5338. }
  5339. public void AddWin32VersionInfo(CompilerOptions options){
  5340. if (options == null) return;
  5341. Writer.AddWin32VersionInfo(this, options);
  5342. }
  5343. #endif
  5344. /// <summary>
  5345. /// Gets the first attribute of the given type in the custom attribute list of this module. Returns null if none found.
  5346. /// This should not be called until the module has been processed to replace symbolic references
  5347. /// to members with references to the actual members.
  5348. /// </summary>
  5349. public virtual AttributeNode GetAttribute(TypeNode attributeType){
  5350. AttributeList attributes = this.GetAttributes(attributeType, 1);
  5351. if (attributes != null && attributes.Count > 0)
  5352. return attributes[0];
  5353. return null;
  5354. }
  5355. public virtual AttributeList GetAttributes(TypeNode attributeType){
  5356. return GetAttributes(attributeType, Int32.MaxValue);
  5357. }
  5358. public virtual AttributeList GetAttributes(TypeNode attributeType, int maxCount){
  5359. AttributeList foundAttributes = new AttributeList();
  5360. if (attributeType == null) return foundAttributes;
  5361. AttributeList attributes = this.Attributes;
  5362. for (int i = 0, count = 0, n = attributes == null ? 0 : attributes.Count; i < n && count < maxCount; i++){
  5363. AttributeNode attr = attributes[i];
  5364. if (attr == null) continue;
  5365. MemberBinding mb = attr.Constructor as MemberBinding;
  5366. if (mb != null){
  5367. if (mb.BoundMember == null) continue;
  5368. if (mb.BoundMember.DeclaringType != attributeType) continue;
  5369. foundAttributes.Add(attr);
  5370. count++;
  5371. continue;
  5372. }
  5373. Literal lit = attr.Constructor as Literal;
  5374. if (lit == null) continue;
  5375. if ((lit.Value as TypeNode) != attributeType) continue;
  5376. foundAttributes.Add(attr);
  5377. count++;
  5378. }
  5379. return foundAttributes;
  5380. }
  5381. #if !NoXml
  5382. protected TrivialHashtable memberDocumentationCache;
  5383. public TrivialHashtable GetMemberDocumentationCache(){
  5384. TrivialHashtable cache = this.memberDocumentationCache;
  5385. if (cache != null) return cache;
  5386. lock(this){
  5387. if (this.memberDocumentationCache != null) return this.memberDocumentationCache;
  5388. XmlDocument doc = this.Documentation;
  5389. if (doc == null && this.ContainingAssembly != null && this.ContainingAssembly != this)
  5390. return this.memberDocumentationCache = this.ContainingAssembly.memberDocumentationCache;
  5391. cache = this.memberDocumentationCache = new TrivialHashtable();
  5392. if (doc == null) return cache;
  5393. XmlNode docElem = doc.DocumentElement;
  5394. if (docElem == null) return cache;
  5395. XmlNode membersNode = null;
  5396. if (docElem.HasChildNodes){
  5397. foreach (XmlNode dec in docElem.ChildNodes)
  5398. if (dec.Name == "members"){membersNode = dec; break;}
  5399. }
  5400. if (membersNode == null) return cache;
  5401. if (membersNode.HasChildNodes){
  5402. foreach (XmlNode member in membersNode.ChildNodes){
  5403. if (member.Name != "member") continue;
  5404. XmlNode nameAttr = member.Attributes.GetNamedItem("name");
  5405. if (nameAttr == null) continue;
  5406. cache[Identifier.For(nameAttr.Value).UniqueIdKey] = member;
  5407. }
  5408. }
  5409. return cache;
  5410. }
  5411. }
  5412. #endif
  5413. protected TrivialHashtable validNamespaces;
  5414. public NamespaceList GetNamespaceList(){
  5415. if (this.reader != null) return this.GetNamespaceListFromReader();
  5416. #if !MinimalReader
  5417. TypeNodeList types = this.Types;
  5418. int n = types == null ? 0 : types.Count;
  5419. if (this.namespaceList == null || n > this.savedTypesLength){
  5420. lock(this){
  5421. if (this.namespaceList != null && this.types != null && this.types.Count == this.savedTypesLength)
  5422. return this.namespaceList;
  5423. NamespaceList nsList = this.namespaceList = new NamespaceList();
  5424. TrivialHashtable nsTable = this.validNamespaces = new TrivialHashtable();
  5425. for (int i = 0; i < n; i++){
  5426. //^ assert this.types != null;
  5427. TypeNode t = this.types[i];
  5428. if (t == null) continue;
  5429. if (t.Namespace == null) t.Namespace = Identifier.Empty;
  5430. Namespace ns = nsTable[t.Namespace.UniqueIdKey] as Namespace;
  5431. if (ns != null){
  5432. if (t.IsPublic) ns.isPublic = true;
  5433. ns.Types.Add(t); continue;
  5434. }
  5435. ns = new Namespace(t.Namespace);
  5436. ns.isPublic = t.IsPublic;
  5437. ns.Types = new TypeNodeList();
  5438. ns.Types.Add(t);
  5439. nsTable[t.Namespace.UniqueIdKey] = ns;
  5440. nsList.Add(ns);
  5441. }
  5442. }
  5443. }
  5444. #endif
  5445. return this.namespaceList;
  5446. }
  5447. private NamespaceList GetNamespaceListFromReader()
  5448. //^ requires this.reader != null;
  5449. {
  5450. if (this.namespaceList == null){
  5451. lock (Module.GlobalLock) {
  5452. this.reader.GetNamespaces();
  5453. NamespaceList nsList = this.namespaceList = this.reader.namespaceList;
  5454. TrivialHashtable nsTable = this.validNamespaces = new TrivialHashtable();
  5455. for (int i = 0, n = nsList == null ? 0 : nsList.Count; i < n; i++) {
  5456. //^ assert nsList != null;
  5457. Namespace ns = nsList[i];
  5458. if (ns == null || ns.Name == null) continue;
  5459. ns.ProvideTypes = new Namespace.TypeProvider(this.GetTypesForNamespace);
  5460. nsTable[ns.Name.UniqueIdKey] = ns;
  5461. }
  5462. }
  5463. }
  5464. return this.namespaceList;
  5465. }
  5466. private void GetTypesForNamespace(Namespace nspace, object handle){
  5467. if (nspace == null || nspace.Name == null) return;
  5468. lock (Module.GlobalLock) {
  5469. int key = nspace.Name.UniqueIdKey;
  5470. TypeNodeList types = this.Types;
  5471. TypeNodeList nsTypes = nspace.Types = new TypeNodeList();
  5472. for (int i = 0, n = types == null ? 0 : types.Count; i < n; i++) {
  5473. TypeNode t = types[i];
  5474. if (t == null || t.Namespace == null) continue;
  5475. if (t.Namespace.UniqueIdKey == key) nsTypes.Add(t);
  5476. }
  5477. }
  5478. }
  5479. public bool IsValidNamespace(Identifier nsName){
  5480. if (nsName == null) return false;
  5481. this.GetNamespaceList();
  5482. //^ assert this.validNamespaces != null;
  5483. return this.validNamespaces[nsName.UniqueIdKey] != null;
  5484. }
  5485. public bool IsValidTypeName(Identifier nsName, Identifier typeName){
  5486. if (nsName == null || typeName == null) return false;
  5487. if (!this.IsValidNamespace(nsName)) return false;
  5488. if (this.reader != null) return this.reader.IsValidTypeName(nsName, typeName);
  5489. return this.GetType(nsName, typeName) != null;
  5490. }
  5491. public Module GetNestedModule(string moduleName){
  5492. if (this.Types == null){ Debug.Assert(false);} //Just get the types to pull in any exported types
  5493. ModuleReferenceList moduleReferences = this.ModuleReferences; //This should now contain all interesting referenced modules
  5494. for (int i = 0, n = moduleReferences == null ? 0 : moduleReferences.Count; i < n; i++){
  5495. ModuleReference mref = moduleReferences[i];
  5496. if (mref == null) continue;
  5497. if (mref.Name == moduleName) return mref.Module;
  5498. }
  5499. return null;
  5500. }
  5501. internal TrivialHashtableUsingWeakReferences/*!*/ StructurallyEquivalentType {
  5502. get {
  5503. if (this.structurallyEquivalentType == null)
  5504. this.structurallyEquivalentType = new TrivialHashtableUsingWeakReferences();
  5505. return this.structurallyEquivalentType;
  5506. }
  5507. }
  5508. private TrivialHashtableUsingWeakReferences structurallyEquivalentType;
  5509. /// <summary>
  5510. /// The identifier represents the structure via some mangling scheme. The result can be either from this module,
  5511. /// or any module this module has a reference to.
  5512. /// </summary>
  5513. public virtual TypeNode GetStructurallyEquivalentType(Identifier ns, Identifier/*!*/ id) {
  5514. return this.GetStructurallyEquivalentType(ns, id, id, true);
  5515. }
  5516. public virtual TypeNode GetStructurallyEquivalentType(Identifier ns, Identifier/*!*/ id, Identifier uniqueMangledName, bool lookInReferencedAssemblies) {
  5517. if (uniqueMangledName == null) uniqueMangledName = id;
  5518. TypeNode result = (TypeNode)this.StructurallyEquivalentType[uniqueMangledName.UniqueIdKey];
  5519. if (result == Class.DoesNotExist) return null;
  5520. if (result != null) return result;
  5521. lock (Module.GlobalLock){
  5522. result = this.GetType(ns, id);
  5523. if (result != null){
  5524. this.StructurallyEquivalentType[uniqueMangledName.UniqueIdKey] = result;
  5525. return result;
  5526. }
  5527. if (!lookInReferencedAssemblies)
  5528. goto notfound;
  5529. AssemblyReferenceList refs = this.AssemblyReferences;
  5530. for (int i = 0, n = refs == null ? 0 : refs.Count; i < n; i++){
  5531. AssemblyReference ar = refs[i];
  5532. if (ar == null) continue;
  5533. AssemblyNode a = ar.Assembly;
  5534. if (a == null) continue;
  5535. result = a.GetType(ns, id);
  5536. if (result != null){
  5537. this.StructurallyEquivalentType[uniqueMangledName.UniqueIdKey] = result;
  5538. return result;
  5539. }
  5540. }
  5541. notfound:
  5542. this.StructurallyEquivalentType[uniqueMangledName.UniqueIdKey] = Class.DoesNotExist;
  5543. return null;
  5544. }
  5545. }
  5546. public virtual TypeNode GetType(Identifier @namespace, Identifier name, bool lookInReferencedAssemblies){
  5547. return this.GetType(@namespace, name, lookInReferencedAssemblies, lookInReferencedAssemblies ? new TrivialHashtable() : null);
  5548. }
  5549. protected virtual TypeNode GetType(Identifier @namespace, Identifier name, bool lookInReferencedAssemblies, TrivialHashtable assembliesAlreadyVisited){
  5550. if (assembliesAlreadyVisited != null) {
  5551. if (assembliesAlreadyVisited[this.UniqueKey] != null) return null;
  5552. assembliesAlreadyVisited[this.UniqueKey] = this;
  5553. }
  5554. TypeNode result = this.GetType(@namespace, name);
  5555. if (result != null || !lookInReferencedAssemblies) return result;
  5556. AssemblyReferenceList refs = this.AssemblyReferences;
  5557. for (int i = 0, n = refs == null ? 0 : refs.Count; i < n; i++) {
  5558. AssemblyReference ar = refs[i];
  5559. if (ar == null) continue;
  5560. AssemblyNode a = ar.Assembly;
  5561. if (a == null) continue;
  5562. result = a.GetType(@namespace, name, true, assembliesAlreadyVisited);
  5563. if (result != null) return result;
  5564. }
  5565. return null;
  5566. }
  5567. public virtual TypeNode GetType(Identifier @namespace, Identifier name){
  5568. if (@namespace == null || name == null) return null;
  5569. TypeNode result = null;
  5570. if (this.namespaceTable == null) this.namespaceTable = new TrivialHashtable();
  5571. TrivialHashtable nsTable = (TrivialHashtable)this.namespaceTable[@namespace.UniqueIdKey];
  5572. if (nsTable != null){
  5573. result = (TypeNode)nsTable[name.UniqueIdKey];
  5574. if (result == Class.DoesNotExist) return null;
  5575. if (result != null) return result;
  5576. }else{
  5577. lock (Module.GlobalLock){
  5578. nsTable = (TrivialHashtable)this.namespaceTable[@namespace.UniqueIdKey];
  5579. if (nsTable == null)
  5580. this.namespaceTable[@namespace.UniqueIdKey] = nsTable = new TrivialHashtable(32);
  5581. }
  5582. }
  5583. if (this.provideTypeNode != null){
  5584. lock (Module.GlobalLock){
  5585. result = (TypeNode)nsTable[name.UniqueIdKey];
  5586. if (result == Class.DoesNotExist) return null;
  5587. if (result != null) return result;
  5588. result = this.provideTypeNode(@namespace, name);
  5589. if (result != null){
  5590. nsTable[name.UniqueIdKey] = result;
  5591. return result;
  5592. }
  5593. nsTable[name.UniqueIdKey] = Class.DoesNotExist;
  5594. return null;
  5595. }
  5596. }
  5597. if (this.types != null && this.types.Count > this.savedTypesLength){
  5598. int n = this.savedTypesLength = this.types.Count;
  5599. for (int i = 0; i < n; i++){
  5600. TypeNode t = this.types[i];
  5601. if (t == null) continue;
  5602. if (t.Namespace == null) t.Namespace = Identifier.Empty;
  5603. nsTable = (TrivialHashtable)this.namespaceTable[t.Namespace.UniqueIdKey];
  5604. if (nsTable == null) this.namespaceTable[t.Namespace.UniqueIdKey] = nsTable = new TrivialHashtable();
  5605. nsTable[t.Name.UniqueIdKey] = t;
  5606. }
  5607. return this.GetType(@namespace, name);
  5608. }
  5609. return null;
  5610. }
  5611. protected internal TypeNodeList types;
  5612. /// <summary>The types contained in this module or assembly.</summary>
  5613. public virtual TypeNodeList Types{
  5614. get{
  5615. if (this.types != null) return this.types;
  5616. if (this.provideTypeNodeList != null){
  5617. lock (Module.GlobalLock){
  5618. if (this.types == null)
  5619. this.provideTypeNodeList(this);
  5620. }
  5621. }else
  5622. this.types = new TypeNodeList();
  5623. return this.types;
  5624. }
  5625. set{
  5626. this.types = value;
  5627. }
  5628. }
  5629. #if !MinimalReader
  5630. protected TrivialHashtable referencedModulesAndAssemblies;
  5631. #endif
  5632. public virtual bool HasReferenceTo(Module module){
  5633. if (module == null) return false;
  5634. AssemblyNode assembly = module as AssemblyNode;
  5635. if (assembly != null){
  5636. AssemblyReferenceList arefs = this.AssemblyReferences;
  5637. for (int i = 0, n = arefs == null ? 0 : arefs.Count; i < n; i++) {
  5638. AssemblyReference aref = arefs[i];
  5639. if (aref == null) continue;
  5640. if (aref.Matches(assembly.Name, assembly.Version, assembly.Culture, assembly.PublicKeyToken))
  5641. return true;
  5642. }
  5643. }
  5644. if (this.ContainingAssembly != module.ContainingAssembly)
  5645. return false;
  5646. ModuleReferenceList mrefs = this.ModuleReferences;
  5647. for (int i = 0, n = mrefs == null ? 0 : mrefs.Count; i < n; i++) {
  5648. //^ assert mrefs != null;
  5649. ModuleReference mref = mrefs[i];
  5650. if (mref == null || mref.Name == null) continue;
  5651. if (0 == PlatformHelpers.StringCompareOrdinalIgnoreCase(mref.Name, module.Name))
  5652. return true;
  5653. }
  5654. return false;
  5655. }
  5656. internal void InitializeAssemblyReferenceResolution(Module referringModule){
  5657. if (this.AssemblyReferenceResolution == null && referringModule != null) {
  5658. this.AssemblyReferenceResolution = referringModule.AssemblyReferenceResolution;
  5659. this.AssemblyReferenceResolutionAfterProbingFailed = referringModule.AssemblyReferenceResolutionAfterProbingFailed;
  5660. }
  5661. }
  5662. #if !MinimalReader
  5663. public static Module GetModule(byte[] buffer){
  5664. return Module.GetModule(buffer, null, false, false, true, false);
  5665. }
  5666. public static Module GetModule(byte[] buffer, IDictionary cache){
  5667. return Module.GetModule(buffer, null, false, false, false, false);
  5668. }
  5669. public static Module GetModule(byte[] buffer, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache){
  5670. return Module.GetModule(buffer, cache, doNotLockFile, getDebugInfo, useGlobalCache, false);
  5671. }
  5672. public static Module GetModule(byte[] buffer, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches){
  5673. if (buffer == null) return null;
  5674. return (new Reader(buffer, cache, doNotLockFile, getDebugInfo, useGlobalCache, false)).ReadModule();
  5675. }
  5676. #endif
  5677. public static Module GetModule(string location){
  5678. return Module.GetModule(location, null, false, false, true, false);
  5679. }
  5680. public static Module GetModule(string location, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache){
  5681. return Module.GetModule(location, null, doNotLockFile, getDebugInfo, useGlobalCache, false);
  5682. }
  5683. public static Module GetModule(string location, IDictionary cache){
  5684. return Module.GetModule(location, cache, false, false, false, false);
  5685. }
  5686. public static Module GetModule(string location, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache){
  5687. return Module.GetModule(location, cache, doNotLockFile, getDebugInfo, useGlobalCache, false);
  5688. }
  5689. public static Module GetModule(string location, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches){
  5690. if (location == null) return null;
  5691. return (new Reader(location, cache, doNotLockFile, getDebugInfo, useGlobalCache, preserveShortBranches)).ReadModule();
  5692. }
  5693. public virtual AssemblyNode Resolve(AssemblyReference assemblyReference){
  5694. if (this.AssemblyReferenceResolution == null) return null;
  5695. return this.AssemblyReferenceResolution(assemblyReference, this);
  5696. }
  5697. public virtual AssemblyNode ResolveAfterProbingFailed(AssemblyReference assemblyReference){
  5698. if (this.AssemblyReferenceResolutionAfterProbingFailed == null) return null;
  5699. return this.AssemblyReferenceResolutionAfterProbingFailed(assemblyReference, this);
  5700. }
  5701. #if !NoWriter
  5702. public virtual void WriteModule(string/*!*/ location, bool writeDebugSymbols) {
  5703. this.Location = location;
  5704. Writer.WritePE(location, writeDebugSymbols, this);
  5705. }
  5706. public virtual void WriteModule(Stream/*!*/ executable, Stream debugSymbols) {
  5707. Writer.WritePE(executable, debugSymbols, this);
  5708. }
  5709. public virtual void WriteModule(out byte[] executable){
  5710. Writer.WritePE(out executable, this);
  5711. }
  5712. public virtual void WriteModule(out byte[] executable, out byte[] debugSymbols){
  5713. Writer.WritePE(out executable, out debugSymbols, this);
  5714. }
  5715. public virtual void WriteModule(string/*!*/ location, System.CodeDom.Compiler.CompilerParameters/*!*/ options) {
  5716. this.Location = location;
  5717. Writer.WritePE(options, this);
  5718. }
  5719. #endif
  5720. #if !NoXml
  5721. public virtual void WriteDocumentation(System.IO.TextWriter doc){
  5722. if (this.documentation == null) return;
  5723. XmlTextWriter xwriter = new XmlTextWriter(doc);
  5724. xwriter.Formatting = Formatting.Indented;
  5725. xwriter.Indentation = 2;
  5726. xwriter.WriteProcessingInstruction("xml", "version=\"1.0\"");
  5727. xwriter.WriteStartElement("doc");
  5728. AssemblyNode assem = this as AssemblyNode;
  5729. if (assem != null){
  5730. xwriter.WriteStartElement("assembly");
  5731. xwriter.WriteElementString("name", assem.Name);
  5732. xwriter.WriteEndElement();
  5733. }
  5734. xwriter.WriteStartElement("members");
  5735. TypeNodeList types = this.Types;
  5736. for (int i = 1, n = types == null ? 0 : types.Count; i < n; i++){
  5737. //^ assert types != null;
  5738. TypeNode t = types[i]; if (t == null) continue;
  5739. t.WriteDocumentation(xwriter);
  5740. }
  5741. xwriter.WriteEndElement();
  5742. xwriter.WriteEndElement();
  5743. xwriter.Close();
  5744. }
  5745. #endif
  5746. #if !NoWriter
  5747. public delegate MethodBodySpecializer/*!*/ MethodBodySpecializerFactory(Module/*!*/ m, TypeNodeList/*!*/ pars, TypeNodeList/*!*/ args);
  5748. public MethodBodySpecializerFactory CreateMethodBodySpecializer;
  5749. public MethodBodySpecializer/*!*/ GetMethodBodySpecializer(TypeNodeList/*!*/ pars, TypeNodeList/*!*/ args) {
  5750. if (CreateMethodBodySpecializer != null)
  5751. return this.CreateMethodBodySpecializer(this, pars, args);
  5752. return new MethodBodySpecializer(this, pars, args);
  5753. }
  5754. #endif
  5755. }
  5756. public class AssemblyNode : Module{ //An assembly is a module with a strong name
  5757. #if !NoWriter
  5758. public string KeyContainerName;
  5759. public byte[] KeyBlob;
  5760. #endif
  5761. #if !NoReflection
  5762. private static Hashtable CompiledAssemblies;// so we can find in-memory compiled assemblies later (contains weak references)
  5763. #endif
  5764. #if !MinimalReader
  5765. protected AssemblyNode contractAssembly;
  5766. /// <summary>A separate assembly that supplied the type and method contracts for this assembly.</summary>
  5767. public virtual AssemblyNode ContractAssembly{
  5768. get{
  5769. return this.contractAssembly;
  5770. }
  5771. set{
  5772. if (this.contractAssembly != null){Debug.Assert(false); return;}
  5773. this.contractAssembly = value;
  5774. if (value == null) return;
  5775. #region Copy over any external references from the contract assembly to this one (if needed)
  5776. // These external references are needed only for the contract deserializer
  5777. AssemblyReferenceList ars = new AssemblyReferenceList();
  5778. AssemblyReferenceList contractReferences = value.AssemblyReferences;
  5779. // see if contractReferences[i] is already in the external references of "this"
  5780. for (int i = 0, n = contractReferences == null ? 0 : contractReferences.Count; i < n; i++){
  5781. //^ assert contractReferences != null;
  5782. AssemblyReference aref = contractReferences[i];
  5783. if (aref == null) continue;
  5784. if (aref.Assembly != this){ // don't copy the contract's external reference to "this"
  5785. int j = 0;
  5786. int m = this.AssemblyReferences == null ? 0 : this.AssemblyReferences.Count;
  5787. while (j < m){
  5788. if (aref.Assembly.Name != null &&
  5789. this.AssemblyReferences[j].Name != null &&
  5790. aref.Assembly.Name.Equals(this.AssemblyReferences[j].Name))
  5791. break;
  5792. j++;
  5793. }
  5794. if (j == m){ // then it wasn't found in the list of the real references
  5795. ars.Add(contractReferences[i]);
  5796. }
  5797. }
  5798. }
  5799. if (this.AssemblyReferences == null)
  5800. this.AssemblyReferences = new AssemblyReferenceList();
  5801. for (int i = 0, n = ars.Count; i < n; i++){
  5802. this.AssemblyReferences.Add(ars[i]);
  5803. }
  5804. #endregion Copy over any external references from the contract assembly to this one (if needed)
  5805. #if ExtendedRuntime
  5806. #region Copy over any assembly-level attributes from the Contracts namespace
  5807. int contractsNamespaceKey = SystemTypes.NonNullType.Namespace.UniqueIdKey;
  5808. // Copy the assembly-level contract attributes over to the shadowed assembly.
  5809. foreach(AttributeNode attr in contractAssembly.Attributes) {
  5810. if(attr.Type != SystemTypes.ShadowsAssemblyAttribute // can't copy this one or the real assembly will be treated as a shadow assembly!
  5811. &&
  5812. attr.Type.Namespace != null && attr.Type.Namespace.UniqueIdKey == contractsNamespaceKey)
  5813. this.Attributes.Add(attr);
  5814. }
  5815. #endregion Copy over any assembly-level attributes from the Contracts namespace
  5816. #endif
  5817. TypeNodeList instantiatedTypes = null;
  5818. if (this.reader != null) instantiatedTypes = this.reader.GetInstantiatedTypes();
  5819. if (instantiatedTypes != null)
  5820. for (int i = 0, n = instantiatedTypes.Count; i < n; i++){
  5821. TypeNode t = instantiatedTypes[i];
  5822. if (t == null) continue;
  5823. if (t.members == null) {
  5824. #if ExtendedRuntime
  5825. // Then will never get to ApplyOutOfBandContracts and will never have any
  5826. // type-level attributes copied over. So need to do this here as well as
  5827. // within ApplyOutOfBandContracts
  5828. TypeNode contractType = this.ContractAssembly.GetType(t.Namespace, t.Name);
  5829. if (contractType == null) continue;
  5830. // Copy the type-level contract attributes over to the shadowed type.
  5831. foreach (AttributeNode attr in contractType.Attributes) {
  5832. if (attr.Type.Namespace != null && attr.Type.Namespace.UniqueIdKey == contractsNamespaceKey)
  5833. t.Attributes.Add(attr);
  5834. }
  5835. #endif
  5836. continue;
  5837. }
  5838. #if ExtendedRuntime
  5839. t.ApplyOutOfBandContracts();
  5840. #endif
  5841. }
  5842. }
  5843. }
  5844. #endif
  5845. internal static readonly AssemblyNode/*!*/ Dummy = new AssemblyNode();
  5846. protected string strongName;
  5847. /// <summary>
  5848. /// A string containing the name, version, culture and key of this assembly, formatted as required by the CLR loader.
  5849. /// </summary>
  5850. public virtual string/*!*/ StrongName{
  5851. get{
  5852. if (this.strongName == null)
  5853. this.strongName = AssemblyNode.GetStrongName(this.Name, this.Version, this.Culture, this.PublicKeyOrToken, (this.Flags & AssemblyFlags.Retargetable) != 0);
  5854. return this.strongName;
  5855. }
  5856. }
  5857. [Obsolete("Please use GetAttribute(TypeNode attributeType)")]
  5858. public virtual AttributeNode GetAttributeByName(TypeNode attributeType){
  5859. if (attributeType == null) return null;
  5860. AttributeList attributes = this.Attributes;
  5861. for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++){
  5862. //^ assert attributes != null;
  5863. AttributeNode attr = attributes[i];
  5864. if (attr == null) continue;
  5865. MemberBinding mb = attr.Constructor as MemberBinding;
  5866. if (mb != null){
  5867. if (mb.BoundMember == null || mb.BoundMember.DeclaringType == null) continue;
  5868. if (mb.BoundMember.DeclaringType.FullName != attributeType.FullName) continue;
  5869. return attr;
  5870. }
  5871. }
  5872. return null;
  5873. }
  5874. /// <summary>
  5875. /// Gets the first attribute of the given type in the custom attribute list of this member. Returns null if none found.
  5876. /// The member is assumed to be either imported, or already in a form suitable for export.
  5877. /// </summary>
  5878. public virtual AttributeNode GetModuleAttribute(TypeNode attributeType){
  5879. if (attributeType == null) return null;
  5880. AttributeList attributes = this.ModuleAttributes;
  5881. for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++){
  5882. //^ assert attributes != null;
  5883. AttributeNode attr = attributes[i];
  5884. if (attr == null) continue;
  5885. MemberBinding mb = attr.Constructor as MemberBinding;
  5886. if (mb != null){
  5887. if (mb.BoundMember == null) continue;
  5888. if (mb.BoundMember.DeclaringType != attributeType) continue;
  5889. return attr;
  5890. }
  5891. Literal lit = attr.Constructor as Literal;
  5892. if (lit == null) continue;
  5893. if ((lit.Value as TypeNode) != attributeType) continue;
  5894. return attr;
  5895. }
  5896. return null;
  5897. }
  5898. public AssemblyNode()
  5899. : base(){
  5900. this.NodeType = NodeType.Assembly;
  5901. this.ContainingAssembly = this;
  5902. }
  5903. public AssemblyNode(TypeNodeProvider provider, TypeNodeListProvider listProvider,
  5904. CustomAttributeProvider provideCustomAttributes, ResourceProvider provideResources, string directory)
  5905. : base(provider, listProvider, provideCustomAttributes, provideResources){
  5906. this.Directory = directory;
  5907. this.NodeType = NodeType.Assembly;
  5908. this.ContainingAssembly = this;
  5909. }
  5910. public override void Dispose(){
  5911. #if !NoReflection
  5912. if (this.cachedRuntimeAssembly != null)
  5913. this.cachedRuntimeAssembly.Dispose();
  5914. this.cachedRuntimeAssembly = null;
  5915. #endif
  5916. lock (Reader.StaticAssemblyCache) {
  5917. foreach (object key in new ArrayList(Reader.StaticAssemblyCache.Keys)){
  5918. if (Reader.StaticAssemblyCache[key] == this)
  5919. Reader.StaticAssemblyCache.Remove(key);
  5920. }
  5921. if(TargetPlatform.AssemblyReferenceForInitialized) {
  5922. AssemblyReference aRef = (AssemblyReference)TargetPlatform.AssemblyReferenceFor[Identifier.For(this.Name).UniqueIdKey];
  5923. if (aRef != null && aRef.Assembly == this){
  5924. aRef.Assembly = null;
  5925. //TODO: what about other static references to the assembly, such as SystemTypes.SystemXmlAssembly?
  5926. }
  5927. }
  5928. }
  5929. base.Dispose();
  5930. }
  5931. private string culture;
  5932. /// <summary>The target culture of any localized resources in this assembly.</summary>
  5933. public string Culture{
  5934. get{return this.culture;}
  5935. set{this.culture = value;}
  5936. }
  5937. private AssemblyFlags flags;
  5938. /// <summary>An enumeration that identifies the what kind of assembly this is.</summary>
  5939. public AssemblyFlags Flags{
  5940. get{return this.flags;}
  5941. set{this.flags = value;}
  5942. }
  5943. private string moduleName;
  5944. /// <summary>Attributes that specifically target a module rather an assembly.</summary>
  5945. public string ModuleName{ //An assembly can have a different name from the module.
  5946. get{return this.moduleName;}
  5947. set{this.moduleName = value;}
  5948. }
  5949. private byte[] publicKeyOrToken;
  5950. /// <summary>The public part of the key pair used to sign this assembly, or a hash of the public key.</summary>
  5951. public byte[] PublicKeyOrToken{
  5952. get{return this.publicKeyOrToken;}
  5953. set{this.publicKeyOrToken = value;}
  5954. }
  5955. private System.Version version;
  5956. /// <summary>The version of this assembly.</summary>
  5957. public System.Version Version{
  5958. get{return this.version;}
  5959. set{this.version = value;}
  5960. }
  5961. private DateTime fileLastWriteTimeUtc;
  5962. public DateTime FileLastWriteTimeUtc{
  5963. get{return this.fileLastWriteTimeUtc;}
  5964. set{this.fileLastWriteTimeUtc = value;}
  5965. }
  5966. protected TypeNodeList exportedTypes;
  5967. /// <summary>
  5968. /// Public types defined in other modules making up this assembly and to which other assemblies may refer to.
  5969. /// </summary>
  5970. public virtual TypeNodeList ExportedTypes{
  5971. get{
  5972. if (this.exportedTypes != null) return this.exportedTypes;
  5973. if (this.provideTypeNodeList != null){
  5974. TypeNodeList types = this.Types; //Gets the exported types as a side-effect
  5975. if (types != null) types = null;
  5976. }else
  5977. this.exportedTypes = new TypeNodeList();
  5978. return this.exportedTypes;
  5979. }
  5980. set{
  5981. this.exportedTypes = value;
  5982. }
  5983. }
  5984. public bool GetDebugSymbols{
  5985. get{
  5986. if (this.reader == null) return false;
  5987. return this.reader.getDebugSymbols;
  5988. }
  5989. set{
  5990. if (this.reader == null) return;
  5991. this.reader.getDebugSymbols = value;
  5992. }
  5993. }
  5994. #if !MinimalReader
  5995. public static AssemblyNode GetAssembly(byte[] buffer){
  5996. return AssemblyNode.GetAssembly(buffer, null, false, false, true, false);
  5997. }
  5998. public static AssemblyNode GetAssembly(byte[] buffer, IDictionary cache){
  5999. return AssemblyNode.GetAssembly(buffer, cache, false, false, false, false);
  6000. }
  6001. public static AssemblyNode GetAssembly(byte[] buffer, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache){
  6002. return AssemblyNode.GetAssembly(buffer, cache, doNotLockFile, getDebugInfo, useGlobalCache, false);
  6003. }
  6004. public static AssemblyNode GetAssembly(byte[] buffer, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches){
  6005. if (buffer == null) return null;
  6006. if (CoreSystemTypes.SystemAssembly == null) Debug.Fail("");
  6007. return (new Reader(buffer, cache, doNotLockFile, getDebugInfo, useGlobalCache, preserveShortBranches)).ReadModule() as AssemblyNode;
  6008. }
  6009. #endif
  6010. public static AssemblyNode GetAssembly(string location){
  6011. return AssemblyNode.GetAssembly(location, null, false, false, true, false);
  6012. }
  6013. public static AssemblyNode GetAssembly(string location, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache){
  6014. return AssemblyNode.GetAssembly(location, null, doNotLockFile, getDebugInfo, useGlobalCache, false);
  6015. }
  6016. public static AssemblyNode GetAssembly(string location, IDictionary cache){
  6017. return AssemblyNode.GetAssembly(location, cache, false, false, false, false);
  6018. }
  6019. public static AssemblyNode GetAssembly(string location, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache){
  6020. return AssemblyNode.GetAssembly(location, cache, doNotLockFile, getDebugInfo, useGlobalCache, false);
  6021. }
  6022. #if !MinimalReader
  6023. /// <summary>
  6024. /// Calls the post load event only if the assembly is not already loaded/found in the cache.
  6025. /// </summary>
  6026. public static AssemblyNode GetAssembly(string location, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, PostAssemblyLoadProcessor postLoadEvent)
  6027. {
  6028. return AssemblyNode.GetAssembly(location, null, doNotLockFile, getDebugInfo, useGlobalCache, false, postLoadEvent);
  6029. }
  6030. public static AssemblyNode GetAssembly(string location, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, PostAssemblyLoadProcessor postLoadEvent)
  6031. {
  6032. return AssemblyNode.GetAssembly(location, cache, doNotLockFile, getDebugInfo, useGlobalCache, false, postLoadEvent);
  6033. }
  6034. public static AssemblyNode GetAssembly(string location, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches)
  6035. {
  6036. return GetAssembly(location, cache, doNotLockFile, getDebugInfo, useGlobalCache, preserveShortBranches, null);
  6037. }
  6038. public static AssemblyNode GetAssembly(string location, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches, PostAssemblyLoadProcessor postLoadEvent)
  6039. {
  6040. if (location == null) return null;
  6041. if (CoreSystemTypes.SystemAssembly == null) Debug.Fail("");
  6042. return (new Reader(location, cache, doNotLockFile, getDebugInfo, useGlobalCache, preserveShortBranches)).ReadModule(postLoadEvent) as AssemblyNode;
  6043. }
  6044. #else
  6045. public static AssemblyNode GetAssembly(string location, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches)
  6046. {
  6047. if (location == null) return null;
  6048. if (CoreSystemTypes.SystemAssembly == null) Debug.Fail("");
  6049. return (new Reader(location, cache, doNotLockFile, getDebugInfo, useGlobalCache, preserveShortBranches)).ReadModule() as AssemblyNode;
  6050. }
  6051. #endif
  6052. #if !MinimalReader || !NoXml || !NoData
  6053. public static AssemblyNode GetAssembly(AssemblyReference assemblyReference){
  6054. return AssemblyNode.GetAssembly(assemblyReference, null, false, false, true, false);
  6055. }
  6056. public static AssemblyNode GetAssembly(AssemblyReference assemblyReference, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache){
  6057. return AssemblyNode.GetAssembly(assemblyReference, null, doNotLockFile, getDebugInfo, useGlobalCache, false);
  6058. }
  6059. public static AssemblyNode GetAssembly(AssemblyReference assemblyReference, IDictionary cache){
  6060. return AssemblyNode.GetAssembly(assemblyReference, cache, false, false, false, false);
  6061. }
  6062. public static AssemblyNode GetAssembly(AssemblyReference assemblyReference, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache){
  6063. return AssemblyNode.GetAssembly(assemblyReference, cache, doNotLockFile, getDebugInfo, useGlobalCache, false);
  6064. }
  6065. public static AssemblyNode GetAssembly(AssemblyReference assemblyReference, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches){
  6066. if (assemblyReference == null) return null;
  6067. if (CoreSystemTypes.SystemAssembly == null) Debug.Fail("");
  6068. Reader reader = new Reader(cache, doNotLockFile, getDebugInfo, useGlobalCache, preserveShortBranches);
  6069. return assemblyReference.Assembly = reader.GetAssemblyFromReference(assemblyReference);
  6070. }
  6071. #endif
  6072. #if !NoReflection
  6073. public static AssemblyNode GetAssembly(System.Reflection.Assembly runtimeAssembly){
  6074. return AssemblyNode.GetAssembly(runtimeAssembly, null, false, true, false);
  6075. }
  6076. public static AssemblyNode GetAssembly(System.Reflection.Assembly runtimeAssembly, IDictionary cache){
  6077. return AssemblyNode.GetAssembly(runtimeAssembly, cache, false, false, false);
  6078. }
  6079. public static AssemblyNode GetAssembly(System.Reflection.Assembly runtimeAssembly, IDictionary cache, bool getDebugInfo, bool useGlobalCache){
  6080. return AssemblyNode.GetAssembly(runtimeAssembly, cache, getDebugInfo, useGlobalCache, false);
  6081. }
  6082. public static AssemblyNode GetAssembly(System.Reflection.Assembly runtimeAssembly, IDictionary cache, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches){
  6083. if (runtimeAssembly == null) return null;
  6084. if (CoreSystemTypes.SystemAssembly == null) Debug.Fail("");
  6085. if (runtimeAssembly.GetName().Name == "mscorlib") {
  6086. return CoreSystemTypes.SystemAssembly;
  6087. }
  6088. if (AssemblyNode.CompiledAssemblies != null) {
  6089. WeakReference weakRef = (WeakReference)AssemblyNode.CompiledAssemblies[runtimeAssembly];
  6090. if (weakRef != null){
  6091. AssemblyNode assem = (AssemblyNode)weakRef.Target;
  6092. if (assem == null) AssemblyNode.CompiledAssemblies.Remove(runtimeAssembly); //Remove the dead WeakReference
  6093. return assem;
  6094. }
  6095. }
  6096. if (runtimeAssembly.Location != null && runtimeAssembly.Location.Length > 0)
  6097. return AssemblyNode.GetAssembly(runtimeAssembly.Location, cache, false, getDebugInfo, useGlobalCache, preserveShortBranches);
  6098. //Get here for in memory assemblies that were not loaded from a known AssemblyNode
  6099. //Need CLR support to handle such assemblies. For now return null.
  6100. return null;
  6101. }
  6102. #endif
  6103. public void SetupDebugReader(string pdbSearchPath){
  6104. if (this.reader == null){Debug.Assert(false); return;}
  6105. this.reader.SetupDebugReader(this.Location, pdbSearchPath);
  6106. }
  6107. internal static string/*!*/ GetStrongName(string name, Version version, string culture, byte[] publicKey, bool retargetable){
  6108. if (version == null) version = new Version();
  6109. StringBuilder result = new StringBuilder();
  6110. result.Append(name);
  6111. result.Append(", Version="); result.Append(version.ToString());
  6112. result.Append(", Culture="); result.Append(((culture == null || culture.Length == 0) ? "neutral" : culture));
  6113. result.Append(AssemblyNode.GetKeyString(publicKey));
  6114. if (retargetable)
  6115. result.Append(", Retargetable=Yes");
  6116. return result.ToString();
  6117. }
  6118. private System.Reflection.AssemblyName assemblyName;
  6119. public System.Reflection.AssemblyName GetAssemblyName(){
  6120. if (this.assemblyName == null){
  6121. System.Reflection.AssemblyName aName = new System.Reflection.AssemblyName();
  6122. if (this.Location != null && this.Location != "unknown:location"){
  6123. StringBuilder sb = new StringBuilder("file:///");
  6124. sb.Append(Path.GetFullPath(this.Location));
  6125. sb.Replace('\\', '/');
  6126. aName.CodeBase = sb.ToString();
  6127. }
  6128. aName.CultureInfo = new System.Globalization.CultureInfo(this.Culture);
  6129. if (this.PublicKeyOrToken != null && this.PublicKeyOrToken.Length > 8)
  6130. aName.Flags = System.Reflection.AssemblyNameFlags.PublicKey;
  6131. if ((this.Flags & AssemblyFlags.Retargetable) != 0)
  6132. aName.Flags |= (System.Reflection.AssemblyNameFlags)AssemblyFlags.Retargetable;
  6133. aName.HashAlgorithm = (System.Configuration.Assemblies.AssemblyHashAlgorithm)this.HashAlgorithm;
  6134. if (this.PublicKeyOrToken != null && this.PublicKeyOrToken.Length > 0)
  6135. aName.SetPublicKey(this.PublicKeyOrToken);
  6136. else
  6137. aName.SetPublicKey(new byte[0]);
  6138. aName.Name = this.Name;
  6139. aName.Version = this.Version;
  6140. switch (this.Flags & AssemblyFlags.CompatibilityMask){
  6141. case AssemblyFlags.NonSideBySideCompatible:
  6142. aName.VersionCompatibility = System.Configuration.Assemblies.AssemblyVersionCompatibility.SameDomain;
  6143. break;
  6144. case AssemblyFlags.NonSideBySideProcess:
  6145. aName.VersionCompatibility = System.Configuration.Assemblies.AssemblyVersionCompatibility.SameProcess;
  6146. break;
  6147. case AssemblyFlags.NonSideBySideMachine:
  6148. aName.VersionCompatibility = System.Configuration.Assemblies.AssemblyVersionCompatibility.SameMachine;
  6149. break;
  6150. }
  6151. this.assemblyName = aName;
  6152. }
  6153. return this.assemblyName;
  6154. }
  6155. #if !NoReflection
  6156. private sealed class CachedRuntimeAssembly : IDisposable{
  6157. internal System.Reflection.Assembly Value;
  6158. internal CachedRuntimeAssembly(System.Reflection.Assembly assembly){
  6159. this.Value = assembly;
  6160. }
  6161. ~CachedRuntimeAssembly(){
  6162. this.Dispose();
  6163. }
  6164. public void Dispose(){
  6165. if (this.Value != null){
  6166. if (AssemblyNode.CompiledAssemblies != null)
  6167. AssemblyNode.CompiledAssemblies.Remove(this.Value);
  6168. }
  6169. this.Value = null;
  6170. GC.SuppressFinalize(this);
  6171. }
  6172. }
  6173. private CachedRuntimeAssembly cachedRuntimeAssembly;
  6174. public System.Reflection.Assembly GetRuntimeAssembly(){
  6175. return this.GetRuntimeAssembly(null, null);
  6176. }
  6177. #endif
  6178. #if !NoReflection
  6179. public System.Reflection.Assembly GetRuntimeAssembly(System.Security.Policy.Evidence evidence){
  6180. return this.GetRuntimeAssembly(evidence, null);
  6181. }
  6182. public System.Reflection.Assembly GetRuntimeAssembly(AppDomain targetAppDomain){
  6183. return this.GetRuntimeAssembly(null, targetAppDomain);
  6184. }
  6185. public System.Reflection.Assembly GetRuntimeAssembly(System.Security.Policy.Evidence evidence, AppDomain targetAppDomain){
  6186. System.Reflection.Assembly result = this.cachedRuntimeAssembly == null ? null : this.cachedRuntimeAssembly.Value;
  6187. if (result == null || evidence != null || targetAppDomain != null){
  6188. lock(this){
  6189. if (this.cachedRuntimeAssembly != null && evidence == null && targetAppDomain == null) return this.cachedRuntimeAssembly.Value;
  6190. if (targetAppDomain == null) targetAppDomain = AppDomain.CurrentDomain;
  6191. if (this.Location != null){
  6192. string name = this.StrongName;
  6193. System.Reflection.Assembly[] alreadyLoadedAssemblies = targetAppDomain.GetAssemblies();
  6194. if (alreadyLoadedAssemblies != null)
  6195. for (int i = 0, n = alreadyLoadedAssemblies.Length; i < n; i++){
  6196. System.Reflection.Assembly a = alreadyLoadedAssemblies[i];
  6197. if (a == null) continue;
  6198. if (a.FullName == name){
  6199. result = a; break;
  6200. }
  6201. }
  6202. if (result == null){
  6203. if (evidence != null)
  6204. result = targetAppDomain.Load(this.GetAssemblyName(), evidence);
  6205. else
  6206. result = targetAppDomain.Load(this.GetAssemblyName());
  6207. }
  6208. }
  6209. #if !NoWriter
  6210. // without the writer, it is impossible to get the runtime
  6211. // assembly for an AssemblyNode which does not correspond
  6212. // to a file on disk, we will return null in that case.
  6213. else{
  6214. byte[] executable = null;
  6215. byte[] debugSymbols = null;
  6216. if ((this.Flags & (AssemblyFlags.EnableJITcompileTracking|AssemblyFlags.DisableJITcompileOptimizer)) != 0){
  6217. this.WriteModule(out executable, out debugSymbols);
  6218. if (evidence != null)
  6219. result = targetAppDomain.Load(executable, debugSymbols, evidence);
  6220. else
  6221. result = targetAppDomain.Load(executable, debugSymbols);
  6222. }else{
  6223. this.WriteModule(out executable);
  6224. if (evidence != null)
  6225. result = targetAppDomain.Load(executable, null, evidence);
  6226. else
  6227. result = targetAppDomain.Load(executable);
  6228. }
  6229. }
  6230. #endif
  6231. if (result != null && evidence == null && targetAppDomain == AppDomain.CurrentDomain){
  6232. this.AddCachedAssembly(result);
  6233. this.cachedRuntimeAssembly = new CachedRuntimeAssembly(result);
  6234. }
  6235. }
  6236. }
  6237. return result;
  6238. }
  6239. private void AddCachedAssembly(System.Reflection.Assembly/*!*/ runtimeAssembly) {
  6240. if (AssemblyNode.CompiledAssemblies == null)
  6241. AssemblyNode.CompiledAssemblies = Hashtable.Synchronized(new Hashtable());
  6242. AssemblyNode.CompiledAssemblies[runtimeAssembly] = new WeakReference(this);
  6243. }
  6244. #endif
  6245. private static string GetKeyString(byte[] publicKey){
  6246. if (publicKey == null) return null;
  6247. int n = publicKey.Length;
  6248. StringBuilder str;
  6249. if (n > 8){
  6250. #if !ROTOR
  6251. System.Security.Cryptography.SHA1 sha1 = new System.Security.Cryptography.SHA1CryptoServiceProvider();
  6252. publicKey = sha1.ComputeHash(publicKey);
  6253. byte[] token = new byte[8];
  6254. for (int i = 0, m = publicKey.Length-1; i < 8; i++)
  6255. token[i] = publicKey[m-i];
  6256. publicKey = token;
  6257. n = 8;
  6258. #else
  6259. n = 0; //TODO: figure out how to compute the token on ROTOR
  6260. #endif
  6261. }
  6262. if (n == 0)
  6263. str = new StringBuilder(", PublicKeyToken=null");
  6264. else
  6265. str = new StringBuilder(", PublicKeyToken=", n*2+17);
  6266. for (int i = 0; i < n; i++)
  6267. str.Append(publicKey[i].ToString("x2"));
  6268. return str.ToString();
  6269. }
  6270. protected TrivialHashtable friends;
  6271. public virtual bool MayAccessInternalTypesOf(AssemblyNode assembly){
  6272. if (this == assembly) return true;
  6273. if (assembly == null || SystemTypes.InternalsVisibleToAttribute == null) return false;
  6274. if (this.friends == null) this.friends = new TrivialHashtable();
  6275. object ob = this.friends[assembly.UniqueKey];
  6276. if (ob == (object)string.Empty) return false;
  6277. if (ob == this) return true;
  6278. AttributeList attributes = assembly.Attributes;
  6279. for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++){
  6280. //^ assert attributes != null;
  6281. AttributeNode attr = attributes[i];
  6282. if (attr == null) continue;
  6283. MemberBinding mb = attr.Constructor as MemberBinding;
  6284. if (mb != null){
  6285. if (mb.BoundMember == null) continue;
  6286. if (mb.BoundMember.DeclaringType != SystemTypes.InternalsVisibleToAttribute) continue;
  6287. }else{
  6288. Literal lit = attr.Constructor as Literal;
  6289. if (lit == null) continue;
  6290. if ((lit.Value as TypeNode) != SystemTypes.InternalsVisibleToAttribute) continue;
  6291. }
  6292. if (attr.Expressions == null || attr.Expressions.Count < 1) continue;
  6293. Literal argLit = attr.Expressions[0] as Literal;
  6294. if (argLit == null) continue;
  6295. string friendName = argLit.Value as string;
  6296. if (friendName == null) continue;
  6297. try{
  6298. AssemblyReference ar = new AssemblyReference(friendName);
  6299. byte[] tok = ar.PublicKeyToken;
  6300. if (tok != null && this.PublicKeyOrToken != null) tok = this.PublicKeyToken;
  6301. if (!ar.Matches(this.Name, ar.Version, ar.Culture, tok)) continue;
  6302. #if !FxCop
  6303. }catch(ArgumentException e){
  6304. if (this.MetadataImportErrors == null) this.MetadataImportErrors = new ArrayList();
  6305. this.MetadataImportErrors.Add(e.Message);
  6306. continue;
  6307. }
  6308. #else
  6309. }finally{}
  6310. #endif
  6311. this.friends[assembly.UniqueKey] = this;
  6312. return true;
  6313. }
  6314. this.friends[assembly.UniqueKey] = string.Empty;
  6315. return false;
  6316. }
  6317. public AssemblyReferenceList GetFriendAssemblies(){
  6318. if (SystemTypes.InternalsVisibleToAttribute == null) return null;
  6319. AttributeList attributes = this.Attributes;
  6320. if (attributes == null) return null;
  6321. int n = attributes.Count; if (n == 0) return null;
  6322. AssemblyReferenceList result = new AssemblyReferenceList(n);
  6323. for (int i = 0; i < n; i++){
  6324. AttributeNode attr = attributes[i];
  6325. if (attr == null) continue;
  6326. MemberBinding mb = attr.Constructor as MemberBinding;
  6327. if (mb != null){
  6328. if (mb.BoundMember == null) continue;
  6329. if (mb.BoundMember.DeclaringType != SystemTypes.InternalsVisibleToAttribute) continue;
  6330. }else{
  6331. Literal lit = attr.Constructor as Literal;
  6332. if (lit == null) continue;
  6333. if ((lit.Value as TypeNode) != SystemTypes.InternalsVisibleToAttribute) continue;
  6334. }
  6335. if (attr.Expressions == null || attr.Expressions.Count < 1) continue;
  6336. Literal argLit = attr.Expressions[0] as Literal;
  6337. if (argLit == null) continue;
  6338. string friendName = argLit.Value as string;
  6339. if (friendName == null) continue;
  6340. result.Add(new AssemblyReference(friendName));
  6341. }
  6342. return result;
  6343. }
  6344. /// <summary>
  6345. /// The attributes associated with this module. This corresponds to C# custom attributes with the module target specifier.
  6346. /// </summary>
  6347. public virtual AttributeList ModuleAttributes {
  6348. get {
  6349. if (this.moduleAttributes != null) return this.moduleAttributes;
  6350. if (this.provideCustomAttributes != null) {
  6351. lock (Module.GlobalLock) {
  6352. if (this.moduleAttributes == null)
  6353. this.provideCustomAttributes(this);
  6354. }
  6355. } else
  6356. this.moduleAttributes = new AttributeList();
  6357. return this.moduleAttributes;
  6358. }
  6359. set {
  6360. this.moduleAttributes = value;
  6361. }
  6362. }
  6363. protected AttributeList moduleAttributes;
  6364. protected byte[] token;
  6365. public virtual byte[] PublicKeyToken{
  6366. get{
  6367. if (this.token != null) return this.token;
  6368. if (this.PublicKeyOrToken == null || this.PublicKeyOrToken.Length == 0) return null;
  6369. if (this.PublicKeyOrToken.Length == 8) return this.token = this.PublicKeyOrToken;
  6370. #if !ROTOR
  6371. System.Security.Cryptography.SHA1 sha1 = new System.Security.Cryptography.SHA1CryptoServiceProvider();
  6372. byte[] hashedKey = sha1.ComputeHash(this.PublicKeyOrToken);
  6373. byte[] token = new byte[8];
  6374. for (int i = 0, n = hashedKey.Length-1; i < 8; i++) token[i] = hashedKey[n-i];
  6375. return this.token = token;
  6376. #else
  6377. return null;
  6378. #endif
  6379. }
  6380. }
  6381. #if !MinimalReader
  6382. public override string ToString() {
  6383. return this.Name;
  6384. }
  6385. public delegate void PostAssemblyLoadProcessor (AssemblyNode loadedAssembly);
  6386. public event PostAssemblyLoadProcessor AfterAssemblyLoad;
  6387. internal PostAssemblyLoadProcessor GetAfterAssemblyLoad()
  6388. {
  6389. return this.AfterAssemblyLoad;
  6390. }
  6391. #endif
  6392. }
  6393. public class AssemblyReference : Node{
  6394. #if !MinimalReader
  6395. public IdentifierList Aliases;
  6396. #endif
  6397. private byte[] token;
  6398. internal Reader Reader;
  6399. public AssemblyReference()
  6400. : base(NodeType.AssemblyReference){
  6401. }
  6402. public AssemblyReference(AssemblyNode/*!*/ assembly)
  6403. : base(NodeType.AssemblyReference){
  6404. this.culture = assembly.Culture;
  6405. this.flags = assembly.Flags & ~AssemblyFlags.PublicKey;
  6406. this.hashValue = assembly.HashValue;
  6407. this.name = assembly.Name;
  6408. this.publicKeyOrToken = assembly.PublicKeyOrToken;
  6409. if (assembly.PublicKeyOrToken != null && assembly.PublicKeyOrToken.Length > 8)
  6410. this.flags |= AssemblyFlags.PublicKey;
  6411. this.location = assembly.Location;
  6412. this.version = assembly.Version;
  6413. this.assembly = assembly;
  6414. }
  6415. #if !MinimalReader
  6416. public AssemblyReference(string assemblyStrongName, SourceContext sctx)
  6417. : this(assemblyStrongName){
  6418. this.SourceContext = sctx;
  6419. }
  6420. #endif
  6421. public AssemblyReference(string assemblyStrongName)
  6422. : base(NodeType.AssemblyReference){
  6423. AssemblyFlags flags = AssemblyFlags.None;
  6424. if (assemblyStrongName == null){Debug.Assert(false); assemblyStrongName = "";}
  6425. int i = 0, n = assemblyStrongName.Length;
  6426. string name = ParseToken(assemblyStrongName, ref i);
  6427. string version = null;
  6428. string culture = null;
  6429. string token = null;
  6430. while (i < n){
  6431. if (assemblyStrongName[i] != ',') throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
  6432. ExceptionStrings.InvalidAssemblyStrongName, assemblyStrongName), "assemblyStrongName");
  6433. i++;
  6434. while (i < n && char.IsWhiteSpace(assemblyStrongName[i])) i++;
  6435. switch (assemblyStrongName[i]){
  6436. case 'v': case 'V': version = ParseAssignment(assemblyStrongName, "Version", ref i); break;
  6437. case 'c': case 'C': culture = ParseAssignment(assemblyStrongName, "Culture", ref i); break;
  6438. case 'p': case 'P':
  6439. if (PlatformHelpers.StringCompareOrdinalIgnoreCase(assemblyStrongName, i, "PublicKeyToken", 0, "PublicKeyToken".Length) == 0)
  6440. token = ParseAssignment(assemblyStrongName, "PublicKeyToken", ref i);
  6441. else {
  6442. token = ParseAssignment(assemblyStrongName, "PublicKey", ref i);
  6443. flags |= AssemblyFlags.PublicKey;
  6444. }
  6445. break;
  6446. case 'r': case 'R':
  6447. string yesOrNo = ParseAssignment(assemblyStrongName, "Retargetable", ref i);
  6448. if (PlatformHelpers.StringCompareOrdinalIgnoreCase(yesOrNo, "Yes") == 0)
  6449. flags |= AssemblyFlags.Retargetable;
  6450. break;
  6451. }
  6452. while (i < n && assemblyStrongName[i] == ']') i++;
  6453. }
  6454. while (i < n && char.IsWhiteSpace(assemblyStrongName[i])) i++;
  6455. if (i < n) throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
  6456. ExceptionStrings.InvalidAssemblyStrongName, assemblyStrongName), "assemblyStrongName");
  6457. if (PlatformHelpers.StringCompareOrdinalIgnoreCase(culture, "neutral") == 0)
  6458. culture = null;
  6459. if (PlatformHelpers.StringCompareOrdinalIgnoreCase(token, "null") == 0)
  6460. token = null;
  6461. byte[] tok = null;
  6462. if (token != null && (n = token.Length) > 0){
  6463. if (n > 16){
  6464. ArrayList tokArr = new ArrayList();
  6465. if (n % 2 == 1){
  6466. tokArr.Add(byte.Parse(token.Substring(0, 1), System.Globalization.NumberStyles.HexNumber, null));
  6467. n--;
  6468. }
  6469. for (i = 0; i < n; i += 2) {
  6470. #if WHIDBEY
  6471. byte b = 0;
  6472. bool goodByte = byte.TryParse(token.Substring(i, 2), System.Globalization.NumberStyles.HexNumber, null, out b);
  6473. Debug.Assert(goodByte);
  6474. #else
  6475. byte b = byte.Parse(token.Substring(i, 2), System.Globalization.NumberStyles.HexNumber, null);
  6476. #endif
  6477. tokArr.Add(b);
  6478. }
  6479. tok = (byte[])tokArr.ToArray(typeof(byte));
  6480. }else{
  6481. ulong tk = ulong.Parse(token, System.Globalization.NumberStyles.HexNumber, null);
  6482. tok = new byte[8];
  6483. tok[0] = (byte)(tk >> 56);
  6484. tok[1] = (byte)(tk >> 48);
  6485. tok[2] = (byte)(tk >> 40);
  6486. tok[3] = (byte)(tk >> 32);
  6487. tok[4] = (byte)(tk >> 24);
  6488. tok[5] = (byte)(tk >> 16);
  6489. tok[6] = (byte)(tk >> 8);
  6490. tok[7] = (byte)tk;
  6491. }
  6492. }
  6493. this.culture = culture;
  6494. this.name = name;
  6495. this.publicKeyOrToken = tok;
  6496. this.version = version == null || version.Length == 0 ? null : new Version(version);
  6497. this.flags = flags;
  6498. }
  6499. private static string ParseToken(string/*!*/ assemblyStrongName, ref int i) {
  6500. Debug.Assert(assemblyStrongName != null);
  6501. int n = assemblyStrongName.Length;
  6502. Debug.Assert(0 <= i && i < n);
  6503. while (i < n && char.IsWhiteSpace(assemblyStrongName[i])) i++;
  6504. StringBuilder sb = new StringBuilder(n);
  6505. while (i < n){
  6506. char ch = assemblyStrongName[i];
  6507. if (ch == ',' || ch == ']' || char.IsWhiteSpace(ch)) break;
  6508. sb.Append(ch);
  6509. i++;
  6510. }
  6511. while (i < n && char.IsWhiteSpace(assemblyStrongName[i])) i++;
  6512. return sb.ToString();
  6513. }
  6514. private static string ParseAssignment(string/*!*/ assemblyStrongName, string/*!*/ target, ref int i) {
  6515. Debug.Assert(assemblyStrongName != null && target != null);
  6516. int n = assemblyStrongName.Length;
  6517. Debug.Assert(0 < i && i < n);
  6518. if (PlatformHelpers.StringCompareOrdinalIgnoreCase(assemblyStrongName, i, target, 0, target.Length) != 0)
  6519. goto throwError;
  6520. i += target.Length;
  6521. while (i < n && char.IsWhiteSpace(assemblyStrongName[i])) i++;
  6522. if (i >= n || assemblyStrongName[i] != '=') goto throwError;
  6523. i++;
  6524. if (i >= n) goto throwError;
  6525. return ParseToken(assemblyStrongName, ref i);
  6526. throwError:
  6527. throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
  6528. ExceptionStrings.InvalidAssemblyStrongName, assemblyStrongName), "assemblyStrongName");
  6529. }
  6530. private string culture;
  6531. public string Culture{
  6532. get{return this.culture;}
  6533. set{this.culture = value;}
  6534. }
  6535. private AssemblyFlags flags;
  6536. public AssemblyFlags Flags{
  6537. get{return this.flags;}
  6538. set{this.flags = value;}
  6539. }
  6540. private byte[] hashValue;
  6541. public byte[] HashValue{
  6542. get{return this.hashValue;}
  6543. set{this.hashValue = value;}
  6544. }
  6545. private string name;
  6546. public string Name{
  6547. get{return this.name;}
  6548. set{this.name = value;}
  6549. }
  6550. private byte[] publicKeyOrToken;
  6551. public byte[] PublicKeyOrToken{
  6552. get{return this.publicKeyOrToken;}
  6553. set{this.publicKeyOrToken = value;}
  6554. }
  6555. private System.Version version;
  6556. public System.Version Version{
  6557. get{return this.version;}
  6558. set{this.version = value;}
  6559. }
  6560. private string location;
  6561. public string Location{
  6562. get{return this.location;}
  6563. set{this.location = value;}
  6564. }
  6565. protected internal AssemblyNode assembly;
  6566. public virtual AssemblyNode Assembly{
  6567. get{
  6568. if (this.assembly != null) return this.assembly;
  6569. if (this.Reader != null)
  6570. return this.assembly = this.Reader.GetAssemblyFromReference(this);
  6571. return null;
  6572. }
  6573. set{
  6574. this.assembly = value;
  6575. }
  6576. }
  6577. protected string strongName;
  6578. public virtual string StrongName{
  6579. get{
  6580. if (this.strongName == null)
  6581. this.strongName = AssemblyNode.GetStrongName(this.Name, this.Version, this.Culture, this.PublicKeyOrToken, (this.Flags & AssemblyFlags.Retargetable) != 0);
  6582. return this.strongName;
  6583. }
  6584. }
  6585. private System.Reflection.AssemblyName assemblyName;
  6586. public System.Reflection.AssemblyName GetAssemblyName(){
  6587. if (this.assemblyName == null){
  6588. System.Reflection.AssemblyName aName = new System.Reflection.AssemblyName();
  6589. aName.CultureInfo = new System.Globalization.CultureInfo(this.Culture == null ? "" : this.Culture);
  6590. if (this.PublicKeyOrToken != null && this.PublicKeyOrToken.Length > 8)
  6591. aName.Flags = System.Reflection.AssemblyNameFlags.PublicKey;
  6592. if ((this.Flags & AssemblyFlags.Retargetable) != 0)
  6593. aName.Flags |= (System.Reflection.AssemblyNameFlags)AssemblyFlags.Retargetable;
  6594. aName.HashAlgorithm = System.Configuration.Assemblies.AssemblyHashAlgorithm.SHA1;
  6595. if (this.PublicKeyOrToken != null){
  6596. if (this.PublicKeyOrToken.Length > 8)
  6597. aName.SetPublicKey(this.PublicKeyOrToken);
  6598. else if (this.PublicKeyOrToken.Length > 0)
  6599. aName.SetPublicKeyToken(this.PublicKeyOrToken);
  6600. }
  6601. else
  6602. aName.SetPublicKey(new byte[0]);
  6603. aName.Name = this.Name;
  6604. aName.Version = this.Version;
  6605. switch (this.Flags & AssemblyFlags.CompatibilityMask){
  6606. case AssemblyFlags.NonSideBySideCompatible:
  6607. aName.VersionCompatibility = System.Configuration.Assemblies.AssemblyVersionCompatibility.SameDomain;
  6608. break;
  6609. case AssemblyFlags.NonSideBySideProcess:
  6610. aName.VersionCompatibility = System.Configuration.Assemblies.AssemblyVersionCompatibility.SameProcess;
  6611. break;
  6612. case AssemblyFlags.NonSideBySideMachine:
  6613. aName.VersionCompatibility = System.Configuration.Assemblies.AssemblyVersionCompatibility.SameMachine;
  6614. break;
  6615. }
  6616. this.assemblyName = aName;
  6617. }
  6618. return this.assemblyName;
  6619. }
  6620. public bool Matches(string name, Version version, string culture, byte[] publicKeyToken){
  6621. if (culture != null && culture.Length == 0) culture = null;
  6622. if (this.Culture != null && this.Culture.Length == 0) this.Culture = null;
  6623. if (this.Version != version && this.Version != null && (version == null || !this.Version.Equals(version))) return false;
  6624. if (PlatformHelpers.StringCompareOrdinalIgnoreCase(this.Name, name) != 0 ||
  6625. PlatformHelpers.StringCompareOrdinalIgnoreCase(this.Culture, culture) != 0) return false;
  6626. if ((this.Flags & AssemblyFlags.Retargetable) != 0) return true;
  6627. byte[] thisToken = this.PublicKeyToken;
  6628. if (publicKeyToken == null) return thisToken == null;
  6629. if (thisToken == publicKeyToken) return true;
  6630. if (thisToken == null) return false;
  6631. int n = publicKeyToken.Length;
  6632. if (n != thisToken.Length) return false;
  6633. for (int i = 0; i < n; i++) if (thisToken[i] != publicKeyToken[i]) return false;
  6634. return true;
  6635. }
  6636. public bool MatchesIgnoringVersion(AssemblyReference reference){
  6637. if (reference == null) return false;
  6638. return this.Matches(reference.Name, this.Version, reference.Culture, reference.PublicKeyToken);
  6639. }
  6640. public byte[] PublicKeyToken{
  6641. get{
  6642. if (this.token != null) return this.token;
  6643. if (this.PublicKeyOrToken == null || this.PublicKeyOrToken.Length == 0) return null;
  6644. if (this.PublicKeyOrToken.Length == 8) return this.token = this.PublicKeyOrToken;
  6645. #if !ROTOR
  6646. System.Security.Cryptography.SHA1 sha = new System.Security.Cryptography.SHA1CryptoServiceProvider();
  6647. byte[] hashedKey = sha.ComputeHash(this.PublicKeyOrToken);
  6648. byte[] token = new byte[8];
  6649. for (int i = 0, n = hashedKey.Length-1; i < 8; i++) token[i] = hashedKey[n-i];
  6650. return this.token = token;
  6651. #else
  6652. return null;
  6653. #endif
  6654. }
  6655. }
  6656. }
  6657. public class ModuleReference : Node{
  6658. private Module module;
  6659. private string name;
  6660. public ModuleReference()
  6661. : base(NodeType.ModuleReference){
  6662. }
  6663. public ModuleReference(string name, Module module)
  6664. : base(NodeType.ModuleReference){
  6665. this.name = name;
  6666. this.module = module;
  6667. }
  6668. public Module Module {
  6669. get{return this.module;}
  6670. set{this.module = value;}
  6671. }
  6672. public string Name{
  6673. get{return this.name;}
  6674. set{this.name = value;}
  6675. }
  6676. }
  6677. /// <summary>
  6678. /// A member of a Namespace or a TypeNode
  6679. /// </summary>
  6680. public abstract class Member : Node{
  6681. #if !MinimalReader
  6682. /// <summary>The namespace of which this node is a member. Null if this node is a member of type.</summary>
  6683. public Namespace DeclaringNamespace;
  6684. /// <summary>
  6685. /// Indicates that the signature of this member may include unsafe types such as pointers. For methods and properties, it also indicates that the
  6686. /// code may contain unsafe constructions such as pointer arithmetic.
  6687. /// </summary>
  6688. public bool IsUnsafe;
  6689. /// <summary>A list of other nodes that refer to this member. Must be filled in by client code.</summary>
  6690. public NodeList References;
  6691. #endif
  6692. protected Member(NodeType nodeType)
  6693. : base(nodeType){
  6694. }
  6695. protected Member(TypeNode declaringType, AttributeList attributes, Identifier name, NodeType nodeType)
  6696. : base(nodeType){
  6697. this.attributes = attributes;
  6698. this.declaringType = declaringType;
  6699. this.name = name;
  6700. }
  6701. private TypeNode declaringType;
  6702. /// <summary>The type of which this node is a member. Null if this node is a member of a Namespace.</summary>
  6703. public TypeNode DeclaringType{
  6704. get{return this.declaringType;}
  6705. set{this.declaringType = value;}
  6706. }
  6707. private Identifier name;
  6708. /// <summary>The unqualified name of the member.</summary>
  6709. public Identifier Name {
  6710. get{return this.name;}
  6711. set{ this.name = value; }
  6712. }
  6713. #if ExtendedRuntime
  6714. private Anonymity anonymity;
  6715. #endif
  6716. protected AttributeList attributes;
  6717. private bool notObsolete;
  6718. private ObsoleteAttribute obsoleteAttribute;
  6719. /// <summary>
  6720. /// The attributes of this member. Corresponds to custom attribute annotations in C#.
  6721. /// </summary>
  6722. public virtual AttributeList Attributes{
  6723. get{
  6724. if (this.attributes != null) return this.attributes;
  6725. return this.attributes = new AttributeList();
  6726. }
  6727. set{
  6728. this.attributes = value;
  6729. }
  6730. }
  6731. protected Member hiddenMember;
  6732. public virtual Member HiddenMember{
  6733. get{
  6734. return this.hiddenMember;
  6735. }
  6736. set{
  6737. this.hiddenMember = value;
  6738. }
  6739. }
  6740. protected bool hidesBaseClassMemberSpecifiedExplicitly;
  6741. protected bool hidesBaseClassMember;
  6742. /// <summary>Indicates if this is a member of a subclass that intentionally has the same signature as a member of a base class. Corresponds to the "new" modifier in C#.</summary>
  6743. public bool HidesBaseClassMember{
  6744. get{
  6745. if (this.hidesBaseClassMemberSpecifiedExplicitly)
  6746. return this.hidesBaseClassMember;
  6747. else
  6748. return this.HiddenMember != null;
  6749. }
  6750. set{
  6751. this.hidesBaseClassMember = value;
  6752. this.hidesBaseClassMemberSpecifiedExplicitly = true;
  6753. }
  6754. }
  6755. protected Member overriddenMember;
  6756. public virtual Member OverriddenMember{
  6757. get{
  6758. return this.overriddenMember;
  6759. }
  6760. set{
  6761. this.overriddenMember = value;
  6762. }
  6763. }
  6764. protected bool overridesBaseClassMemberSpecifiedExplicitly;
  6765. protected bool overridesBaseClassMember;
  6766. /// <summary>Indicates if this is a virtual method of a subclass that intentionally overrides a method of a base class. Corresponds to the "override" modifier in C#.</summary>
  6767. public virtual bool OverridesBaseClassMember{
  6768. get{
  6769. if (this.overridesBaseClassMemberSpecifiedExplicitly)
  6770. return this.overridesBaseClassMember;
  6771. else
  6772. return this.OverriddenMember != null;
  6773. }
  6774. set{
  6775. this.overridesBaseClassMember = value;
  6776. this.overridesBaseClassMemberSpecifiedExplicitly = true;
  6777. }
  6778. }
  6779. /// <summary>
  6780. /// Gets the first attribute of the given type in the attribute list of this member. Returns null if none found.
  6781. /// This should not be called until the AST containing this member has been processed to replace symbolic references
  6782. /// to members with references to the actual members.
  6783. /// </summary>
  6784. public virtual AttributeNode GetAttribute(TypeNode attributeType) {
  6785. if (attributeType == null) return null;
  6786. AttributeList attributes = this.Attributes;
  6787. for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++) {
  6788. AttributeNode attr = attributes[i];
  6789. if (attr == null) continue;
  6790. MemberBinding mb = attr.Constructor as MemberBinding;
  6791. if (mb != null) {
  6792. if (mb.BoundMember == null) continue;
  6793. if (mb.BoundMember.DeclaringType != attributeType) continue;
  6794. return attr;
  6795. }
  6796. Literal lit = attr.Constructor as Literal;
  6797. if (lit == null) continue;
  6798. if ((lit.Value as TypeNode) != attributeType) continue;
  6799. return attr;
  6800. }
  6801. return null;
  6802. }
  6803. public virtual AttributeList GetFilteredAttributes(TypeNode attributeType){
  6804. if (attributeType == null) return this.Attributes;
  6805. AttributeList attributes = this.Attributes;
  6806. AttributeList filtered = new AttributeList();
  6807. for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++) {
  6808. AttributeNode attr = attributes[i];
  6809. if (attr == null) continue;
  6810. MemberBinding mb = attr.Constructor as MemberBinding;
  6811. if (mb != null) {
  6812. if (mb.BoundMember != null && mb.BoundMember.DeclaringType == attributeType) continue;
  6813. filtered.Add(attr);
  6814. continue;
  6815. }
  6816. Literal lit = attr.Constructor as Literal;
  6817. if (lit != null && (lit.Value as TypeNode) == attributeType) continue;
  6818. filtered.Add(attr);
  6819. }
  6820. return filtered;
  6821. }
  6822. #if ExtendedRuntime
  6823. public virtual AttributeList GetAllAttributes(TypeNode attributeType)
  6824. {
  6825. AttributeList filtered = new AttributeList();
  6826. if (attributeType == null) return filtered;
  6827. AttributeList attributes = this.Attributes;
  6828. for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++) {
  6829. AttributeNode attr = attributes[i];
  6830. if (attr == null) continue;
  6831. MemberBinding mb = attr.Constructor as MemberBinding;
  6832. if (mb != null) {
  6833. if (mb.BoundMember != null && mb.BoundMember.DeclaringType == attributeType)
  6834. filtered.Add(attr);
  6835. continue;
  6836. }
  6837. Literal lit = attr.Constructor as Literal;
  6838. if (lit != null && (lit.Value as TypeNode) == attributeType)
  6839. filtered.Add(attr);
  6840. }
  6841. return filtered;
  6842. }
  6843. /// <summary>
  6844. /// If this is true, the name of the member is meaningless and the member is intended as an "invisible" container for other members.
  6845. /// The value of this property is controlled by the presence or absence of the Anonymous attribute.
  6846. /// </summary>
  6847. public bool IsAnonymous{
  6848. get{
  6849. switch (this.Anonymity){
  6850. case Anonymity.None:
  6851. case Anonymity.Unknown:
  6852. return false;
  6853. default:
  6854. return true;
  6855. }
  6856. }
  6857. }
  6858. /// <summary>
  6859. /// Exposes the value of the Anonymous attribute. The value is Anonimity.None if no attribute is present.
  6860. /// </summary>
  6861. public Anonymity Anonymity{
  6862. get{
  6863. if (this.anonymity == Anonymity.Unknown){
  6864. AttributeNode attr = this.GetAttribute(SystemTypes.AnonymousAttribute);
  6865. if (attr == null)
  6866. this.anonymity = Anonymity.None;
  6867. else{
  6868. this.anonymity = Anonymity.Structural; // default
  6869. if (attr.Expressions != null){
  6870. for (int i = 0, n = attr.Expressions.Count; i < n; i++){
  6871. NamedArgument na = attr.Expressions[i] as NamedArgument;
  6872. if (na == null || na.Name != null) continue;
  6873. if (na.Name.UniqueIdKey == StandardIds.Anonymity.UniqueIdKey){
  6874. Literal lit = na.Value as Literal;
  6875. if (lit == null) continue;
  6876. this.anonymity = (Anonymity)lit.Value;
  6877. break;
  6878. }
  6879. }
  6880. }
  6881. }
  6882. }
  6883. return this.anonymity;
  6884. }
  6885. }
  6886. CciMemberKind cciKind;
  6887. public CciMemberKind CciKind{
  6888. get{
  6889. if (cciKind == CciMemberKind.Unknown){
  6890. AttributeNode a = GetAttribute(SystemTypes.CciMemberKindAttribute);
  6891. if (a == null)
  6892. cciKind = CciMemberKind.Regular;
  6893. else
  6894. cciKind = (CciMemberKind) ((Literal) a.Expressions[0]).Value;
  6895. }
  6896. return cciKind;
  6897. }
  6898. set{
  6899. this.cciKind = value;
  6900. }
  6901. }
  6902. #endif
  6903. /// <summary>
  6904. /// The concatenation of the FullName of the containing member and the name of this member.
  6905. /// Separated with a '.' character if the containing member is a namespace and a '+' character if the containing member is a Type.
  6906. /// Includes the parameter type full names when this member is a method or a property. Also includes (generic) template arguments.
  6907. /// </summary>
  6908. public abstract string/*!*/ FullName { get;}
  6909. /// <summary>True if all references to this member must be from the assembly containing the definition of this member. </summary>
  6910. public abstract bool IsAssembly{get;}
  6911. /// <summary>
  6912. /// True if access to this member is controlled by the compiler and not the runtime. Cannot be accessed from other assemblies since these
  6913. /// are not necessarily controlled by the same compiler.
  6914. /// </summary>
  6915. public abstract bool IsCompilerControlled{get;}
  6916. /// <summary>True if this member can only be accessed from subclasses of the class declaring this member.</summary>
  6917. public abstract bool IsFamily{get;}
  6918. /// <summary>True if this member can only be accessed from subclasses of the class declaring this member, provided that these subclasses are also
  6919. /// contained in the assembly containing this member.</summary>
  6920. public abstract bool IsFamilyAndAssembly{get;}
  6921. /// <summary>True if all references to this member must either be from the assembly containing the definition of this member,
  6922. /// or from a subclass of the class declaring this member.</summary>
  6923. public abstract bool IsFamilyOrAssembly{get;}
  6924. /// <summary>True if all references to this member must be from members of the type declaring this member./// </summary>
  6925. public abstract bool IsPrivate{get;}
  6926. /// <summary>True if the member can be accessed from anywhere./// </summary>
  6927. public abstract bool IsPublic{get;}
  6928. /// <summary>True if the name of this member conforms to a naming pattern with special meaning. For example the name of a property getter.</summary>
  6929. public abstract bool IsSpecialName{get;}
  6930. /// <summary>True if this member always has the same value or behavior for all instances the declaring type.</summary>
  6931. public abstract bool IsStatic{get;}
  6932. /// <summary>True if another assembly can contain a reference to this member.</summary>
  6933. public abstract bool IsVisibleOutsideAssembly{get;}
  6934. /// <summary>A cached reference to the first Obsolete attribute of this member. Null if no such attribute exsits.</summary>
  6935. public ObsoleteAttribute ObsoleteAttribute{
  6936. get{
  6937. if (this.notObsolete) return null;
  6938. if (this.obsoleteAttribute == null){
  6939. AttributeNode attr = this.GetAttribute(SystemTypes.ObsoleteAttribute);
  6940. if (attr != null){
  6941. ExpressionList args = attr.Expressions;
  6942. int numArgs = args == null ? 0 : args.Count;
  6943. Literal lit0 = numArgs > 0 ? args[0] as Literal : null;
  6944. Literal lit1 = numArgs > 1 ? args[1] as Literal : null;
  6945. string message = lit0 != null ? lit0.Value as string : null;
  6946. object isError = lit1 != null ? lit1.Value : null;
  6947. if (isError is bool)
  6948. return this.obsoleteAttribute = new ObsoleteAttribute(message, (bool)isError);
  6949. else
  6950. return this.obsoleteAttribute = new ObsoleteAttribute(message);
  6951. }
  6952. this.notObsolete = true;
  6953. }
  6954. return this.obsoleteAttribute;
  6955. }
  6956. set{
  6957. this.obsoleteAttribute = value;
  6958. this.notObsolete = false;
  6959. }
  6960. }
  6961. #if !MinimalReader
  6962. /// <summary>The source code, if any, corresponding to the value in Documentation.</summary>
  6963. public Node DocumentationNode;
  6964. #endif
  6965. #if !NoXml
  6966. protected XmlNode documentation;
  6967. /// <summary>The body of an XML element containing a description of this member. Used to associated documentation (such as this comment) with members.
  6968. /// The fragment usually conforms to the structure defined in the C# standard.</summary>
  6969. public virtual XmlNode Documentation{
  6970. get{
  6971. XmlNode documentation = this.documentation;
  6972. if (documentation != null) return documentation;
  6973. TypeNode t = this.DeclaringType;
  6974. if (t == null) t = this as TypeNode;
  6975. Module m = t == null ? null : t.DeclaringModule;
  6976. TrivialHashtable cache = m == null ? null : m.GetMemberDocumentationCache();
  6977. if (cache == null) return null;
  6978. return this.documentation = (XmlNode)cache[this.DocumentationId.UniqueIdKey];
  6979. }
  6980. set{
  6981. this.documentation = value;
  6982. }
  6983. }
  6984. protected Identifier documentationId;
  6985. protected virtual Identifier GetDocumentationId(){
  6986. return Identifier.Empty;
  6987. }
  6988. /// <summary>
  6989. /// The value of the name attribute of the XML element whose body is the XML fragment returned by Documentation.
  6990. /// </summary>
  6991. public Identifier DocumentationId{
  6992. get{
  6993. Identifier documentationId = this.documentationId;
  6994. if (documentationId != null) return documentationId;
  6995. return this.DocumentationId = this.GetDocumentationId();
  6996. }
  6997. set{
  6998. this.documentationId = value;
  6999. }
  7000. }
  7001. protected string helpText;
  7002. /// <summary>
  7003. /// The value of the summary child element of the XML fragment returned by Documentation. All markup is stripped from the value.
  7004. /// </summary>
  7005. public virtual string HelpText{
  7006. get{
  7007. string helpText = this.helpText;
  7008. if (helpText != null) return helpText;
  7009. XmlNode documentation = this.Documentation;
  7010. if (documentation != null && documentation.HasChildNodes){
  7011. //^ assume documentation.ChildNodes != null;
  7012. foreach (XmlNode child in documentation.ChildNodes)
  7013. if (child.Name == "summary")
  7014. return this.helpText = this.GetHelpText(child);
  7015. }
  7016. return this.helpText = "";
  7017. }
  7018. set{
  7019. this.helpText = value;
  7020. }
  7021. }
  7022. public virtual string GetParameterHelpText(string parameterName){
  7023. XmlNode documentation = this.Documentation;
  7024. if (documentation == null || documentation.ChildNodes == null) return null;
  7025. foreach (XmlNode cdoc in documentation.ChildNodes){
  7026. if (cdoc == null) continue;
  7027. if (cdoc.Name != "param") continue;
  7028. if (cdoc.Attributes == null) continue;
  7029. foreach (XmlAttribute attr in cdoc.Attributes){
  7030. if (attr == null || attr.Name != "name" || attr.Value != parameterName) continue;
  7031. if (!cdoc.HasChildNodes) continue;
  7032. return this.GetHelpText(cdoc);
  7033. }
  7034. }
  7035. return null;
  7036. }
  7037. private string GetHelpText(XmlNode node){
  7038. if (node == null) return "";
  7039. StringBuilder sb = new StringBuilder();
  7040. if (node.HasChildNodes){
  7041. foreach (XmlNode child in node.ChildNodes){
  7042. switch (child.NodeType){
  7043. case XmlNodeType.Element:
  7044. string str = this.GetHelpText(child);
  7045. if (str == null || str.Length == 0) continue;
  7046. if (sb.Length > 0 && !Char.IsPunctuation(str[0]))
  7047. sb.Append(' ');
  7048. sb.Append(str);
  7049. break;
  7050. case XmlNodeType.CDATA:
  7051. case XmlNodeType.Entity:
  7052. case XmlNodeType.Text:
  7053. this.AppendValue(sb, child);
  7054. break;
  7055. }
  7056. }
  7057. }else if (node.Attributes != null){
  7058. foreach (XmlAttribute attr in node.Attributes){
  7059. this.AppendValue(sb, attr);
  7060. }
  7061. }
  7062. return sb.ToString();
  7063. }
  7064. private int filterPriority;
  7065. public virtual System.ComponentModel.EditorBrowsableState FilterPriority {
  7066. get {
  7067. if (this.filterPriority > 0) return (System.ComponentModel.EditorBrowsableState)(this.filterPriority-1);
  7068. int prio = 0;
  7069. XmlNode documentation = this.Documentation;
  7070. if (documentation != null && documentation.HasChildNodes) {
  7071. foreach (XmlNode child in documentation.ChildNodes)
  7072. if (child.Name == "filterpriority") {
  7073. PlatformHelpers.TryParseInt32(child.InnerText, out prio);
  7074. switch (prio) {
  7075. case 2: this.filterPriority = (int)System.ComponentModel.EditorBrowsableState.Advanced; break;
  7076. case 3: this.filterPriority = (int)System.ComponentModel.EditorBrowsableState.Never; break;
  7077. default: this.filterPriority = (int)System.ComponentModel.EditorBrowsableState.Always; break;
  7078. }
  7079. this.filterPriority++;
  7080. return (System.ComponentModel.EditorBrowsableState)(this.filterPriority - 1);
  7081. }
  7082. }
  7083. AttributeList attributes = this.Attributes;
  7084. for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++){
  7085. //^ assert attributes != null;
  7086. AttributeNode attr = attributes[i];
  7087. if (attr == null || attr.Type == null) continue;
  7088. if (attr.Expressions == null || attr.Expressions.Count < 1) continue;
  7089. if (attr.Type.FullName != "System.ComponentModel.EditorBrowsableAttribute") continue;
  7090. Literal lit = attr.Expressions[0] as Literal;
  7091. if (lit == null || !(lit.Value is int)) continue;
  7092. //^ assert lit.Value != null;
  7093. prio = (int)lit.Value;
  7094. return (System.ComponentModel.EditorBrowsableState)((this.filterPriority = prio+1) - 1);
  7095. }
  7096. return (System.ComponentModel.EditorBrowsableState)((this.filterPriority = 1) - 1);
  7097. }
  7098. set {
  7099. this.filterPriority = ((int)value)+1;
  7100. }
  7101. }
  7102. /// <summary>
  7103. /// Writes out an element with tag "element", name attribute DocumentationId.ToString() and body Documentation using the provided XmlTextWriter instance.
  7104. /// </summary>
  7105. public virtual void WriteDocumentation(XmlTextWriter xwriter){
  7106. if (this.documentation == null || xwriter == null) return;
  7107. xwriter.WriteStartElement("member");
  7108. if (this.DocumentationId == null) return;
  7109. xwriter.WriteAttributeString("name", this.DocumentationId.ToString());
  7110. this.documentation.WriteContentTo(xwriter);
  7111. xwriter.WriteEndElement();
  7112. }
  7113. private readonly static char[]/*!*/ tags = {'E', 'F', 'M', 'P', 'T'};
  7114. private void AppendValue(StringBuilder/*!*/ sb, XmlNode/*!*/ node) {
  7115. string str = node.Value;
  7116. if (str != null){
  7117. str = str.Trim();
  7118. if (str.Length > 2 && str[1] == ':' && str.LastIndexOfAny(tags, 0, 1) == 0){
  7119. char tag = str[0];
  7120. str = str.Substring(2);
  7121. if (tag == 'T' && str.IndexOf(TargetPlatform.GenericTypeNamesMangleChar) >= 0) {
  7122. Module mod = null;
  7123. if (this.DeclaringType != null)
  7124. mod = this.DeclaringType.DeclaringModule;
  7125. else if (this is TypeNode)
  7126. mod = ((TypeNode)this).DeclaringModule;
  7127. if (mod != null){
  7128. Identifier ns;
  7129. Identifier tn;
  7130. int i = str.LastIndexOf('.');
  7131. if (i < 0 || i >= str.Length){
  7132. ns = Identifier.Empty;
  7133. tn = Identifier.For(str);
  7134. }else{
  7135. ns = Identifier.For(str.Substring(0, i));
  7136. tn = Identifier.For(str.Substring(i + 1));
  7137. }
  7138. TypeNode t = mod.GetType(ns, tn, true);
  7139. if (t != null) str = t.GetFullUnmangledNameWithTypeParameters();
  7140. }
  7141. }
  7142. }
  7143. if (str == null || str.Length == 0) return;
  7144. bool lastCharWasSpace = false;
  7145. if (sb.Length > 0 && !Char.IsPunctuation(str[0]) && !Char.IsWhiteSpace(str[0])){
  7146. sb.Append(' ');
  7147. lastCharWasSpace = true;
  7148. }
  7149. foreach (char ch in str){
  7150. if (Char.IsWhiteSpace(ch)){
  7151. if (lastCharWasSpace) continue;
  7152. lastCharWasSpace = true;
  7153. sb.Append(' ');
  7154. }else{
  7155. lastCharWasSpace = false;
  7156. sb.Append(ch);
  7157. }
  7158. }
  7159. if (sb.Length > 0 && Char.IsWhiteSpace(sb[sb.Length-1]))
  7160. sb.Length -= 1;
  7161. }
  7162. }
  7163. #endif
  7164. #if FxCop
  7165. internal string GetName(MemberFormat options)
  7166. {
  7167. StringBuilder name = new StringBuilder();
  7168. GetName(options, name);
  7169. return name.ToString();
  7170. }
  7171. internal virtual void GetName(MemberFormat options, StringBuilder name)
  7172. {
  7173. if (options.Type.TypeName != TypeNameFormat.None && this.DeclaringType != null)
  7174. {
  7175. this.DeclaringType.GetName(options, name);
  7176. name.Append('.');
  7177. }
  7178. name.Append(this.Name.Name);
  7179. }
  7180. #endif
  7181. }
  7182. #if !MinimalReader
  7183. public class TypeMemberSnippet : Member{
  7184. public IParserFactory ParserFactory;
  7185. public TypeMemberSnippet()
  7186. : base(NodeType.TypeMemberSnippet){
  7187. }
  7188. public TypeMemberSnippet(IParserFactory parserFactory, SourceContext sctx)
  7189. : base(NodeType.TypeMemberSnippet){
  7190. this.ParserFactory = parserFactory;
  7191. this.SourceContext = sctx;
  7192. }
  7193. public override string/*!*/ FullName {
  7194. get{throw new InvalidOperationException();}
  7195. }
  7196. public override bool IsCompilerControlled{
  7197. get{throw new InvalidOperationException();}
  7198. }
  7199. public override bool IsAssembly{
  7200. get{throw new InvalidOperationException();}
  7201. }
  7202. public override bool IsFamily{
  7203. get{throw new InvalidOperationException();}
  7204. }
  7205. public override bool IsFamilyAndAssembly{
  7206. get{throw new InvalidOperationException();}
  7207. }
  7208. public override bool IsFamilyOrAssembly{
  7209. get{throw new InvalidOperationException();}
  7210. }
  7211. public override bool IsPrivate{
  7212. get{throw new InvalidOperationException();}
  7213. }
  7214. public override bool IsPublic{
  7215. get{throw new InvalidOperationException();}
  7216. }
  7217. public override bool IsSpecialName{
  7218. get{throw new InvalidOperationException();}
  7219. }
  7220. public override bool IsStatic{
  7221. get{throw new InvalidOperationException();}
  7222. }
  7223. public override bool IsVisibleOutsideAssembly {
  7224. get{throw new InvalidOperationException();}
  7225. }
  7226. }
  7227. #endif
  7228. /// <summary>
  7229. /// The common base class for all types. This type should not be extended directly.
  7230. /// Instead extend one of the standard subclasses such as Class, Struct or Interface, since in
  7231. /// the CLR a type has to be an instance of one the subclasses, and a type which does not extend
  7232. /// one of these types will have no equivalent in the CLR.
  7233. /// </summary>
  7234. public abstract class TypeNode : Member
  7235. #if ExtendedRuntime
  7236. , IEquatable<TypeNode>
  7237. #endif
  7238. {
  7239. #if ExtendedRuntime
  7240. /// <summary>The invariants and modelfield contracts associated with this type (for now only classes, interfaces, structs).</summary>
  7241. public TypeContract Contract;
  7242. #endif
  7243. private int classSize;
  7244. /// <summary>Specifies the total size in bytes of instances of types with prescribed layout.</summary>
  7245. public int ClassSize{
  7246. get{return this.classSize;}
  7247. set{this.classSize = value;}
  7248. }
  7249. private Module declaringModule;
  7250. /// <summary>The module or assembly to which the compiled type belongs.</summary>
  7251. public Module DeclaringModule{
  7252. get{return this.declaringModule;}
  7253. set{this.declaringModule = value;}
  7254. }
  7255. private TypeFlags flags;
  7256. public TypeFlags Flags{
  7257. get{return this.flags;}
  7258. set{this.flags = value;}
  7259. }
  7260. /// <summary>The interfaces implemented by this class or struct, or the extended by this interface.</summary>
  7261. public virtual InterfaceList Interfaces {
  7262. get { if (this.interfaces == null) { this.interfaces = new InterfaceList(0);} return this.interfaces; }
  7263. set { this.interfaces = value; }
  7264. }
  7265. protected InterfaceList interfaces;
  7266. #if !MinimalReader
  7267. public InterfaceList InterfaceExpressions;
  7268. #endif
  7269. private Identifier @namespace;
  7270. /// <summary>The namespace to which this type belongs. Null if the type is nested inside another type.</summary>
  7271. public Identifier Namespace{
  7272. get{return this.@namespace;}
  7273. set{this.@namespace = value;}
  7274. }
  7275. private int packingSize;
  7276. /// <summary>Specifies the alignment of fields within types with prescribed layout.</summary>
  7277. public int PackingSize{
  7278. get{return this.packingSize;}
  7279. set{this.packingSize = value;}
  7280. }
  7281. #if !MinimalReader
  7282. /// <summary>If this type is the combined result of a number of partial type definitions, this lists the partial definitions.</summary>
  7283. public TypeNodeList IsDefinedBy;
  7284. #endif
  7285. /// <summary>
  7286. /// True if this type is the result of a template instantiation with arguments that are themselves template parameters.
  7287. /// Used to model template instantiations occurring inside templates.
  7288. /// </summary>
  7289. public bool IsNotFullySpecialized;
  7290. public bool NewTemplateInstanceIsRecursive;
  7291. #if !MinimalReader
  7292. /// <summary>
  7293. /// If this type is a partial definition, the value of this is the combined type resulting from all the partial definitions.
  7294. /// </summary>
  7295. public TypeNode PartiallyDefines;
  7296. /// <summary>
  7297. /// The list of extensions of this type, if it's a non-extension type.
  7298. /// all extensions implement the IExtendTypeNode interface (in the Sing# code base).
  7299. /// null = empty list
  7300. /// </summary>
  7301. private TypeNodeList extensions = null;
  7302. /// <summary>
  7303. /// Whether or not the list of extensions has been examined;
  7304. /// it's a bug to record a new extension after extensions have been examined.
  7305. /// </summary>
  7306. private bool extensionsExamined = false;
  7307. /// <summary>
  7308. /// Record another extension of this type.
  7309. /// </summary>
  7310. /// <param name="extension"></param>
  7311. public void RecordExtension(TypeNode extension) {
  7312. Debug.Assert(!extensionsExamined, "adding an extension after they've already been examined");
  7313. if (this.extensions == null) this.extensions = new TypeNodeList();
  7314. this.extensions.Add(extension);
  7315. }
  7316. /// <summary>
  7317. /// The property that should be accessed by clients to get the list of extensions of this type.
  7318. /// </summary>
  7319. public TypeNodeList Extensions {
  7320. get {
  7321. this.extensionsExamined = true;
  7322. return this.extensions;
  7323. }
  7324. set {
  7325. Debug.Assert(!extensionsExamined, "setting extensions after they've already been examined");
  7326. this.extensions = value;
  7327. }
  7328. }
  7329. /// <summary>
  7330. /// When duplicating a type node, we want to transfer the extensions and the extensionsExamined flag without
  7331. /// treating this as a "touch" that sets the examined flag. Pretty ugly, though.
  7332. /// </summary>
  7333. public TypeNodeList ExtensionsNoTouch{
  7334. get{ return this.extensions; }
  7335. }
  7336. /// <summary>
  7337. /// Copy a (possibly transformed) set of extensions from source to the
  7338. /// receiver, including whether or not the extensions have been examined.
  7339. /// </summary>
  7340. public void DuplicateExtensions(TypeNode source, TypeNodeList newExtensions){
  7341. if (source == null) return;
  7342. this.extensions = newExtensions;
  7343. this.extensionsExamined = source.extensionsExamined;
  7344. }
  7345. /// <summary>
  7346. /// If the receiver is a type extension, return the extendee, otherwise return the receiver.
  7347. /// [The identity function, except for dialects (e.g. Extensible Sing#) that allow
  7348. /// extensions and differing views of types]
  7349. /// </summary>
  7350. public virtual TypeNode/*!*/ EffectiveTypeNode{
  7351. get{
  7352. return this;
  7353. }
  7354. }
  7355. /// <summary>
  7356. /// Return whether t1 represents the same type as t2 (or both are null).
  7357. /// This copes with the cases where t1 and/or t2 may be type views and/or type extensions, as
  7358. /// in Extensible Sing#.
  7359. /// </summary>
  7360. public static bool operator ==(TypeNode t1, TypeNode t2){
  7361. return
  7362. (object)t1 == null ?
  7363. (object)t2 == null :
  7364. (object)t2 != null && (object)t1.EffectiveTypeNode == (object)t2.EffectiveTypeNode;
  7365. }
  7366. // modify the other operations related to equality
  7367. public static bool operator !=(TypeNode t1, TypeNode t2){
  7368. return !(t1 == t2);
  7369. }
  7370. public override bool Equals(Object other){
  7371. return this == (other as TypeNode);
  7372. }
  7373. #if ExtendedRuntime
  7374. public bool Equals(TypeNode other)
  7375. {
  7376. return this == other;
  7377. }
  7378. #endif
  7379. public override int GetHashCode(){
  7380. TypeNode tn = this.EffectiveTypeNode;
  7381. if ((object)tn == (object)this){
  7382. return base.GetHashCode();
  7383. } else {
  7384. return tn.GetHashCode();
  7385. }
  7386. }
  7387. #endif
  7388. /// <summary>
  7389. /// A delegate that is called the first time Members is accessed, if non-null.
  7390. /// Provides for incremental construction of the type node.
  7391. /// Must not leave Members null.
  7392. /// </summary>
  7393. public TypeMemberProvider ProvideTypeMembers;
  7394. /// <summary>
  7395. /// The type of delegates that fill in the Members property of the given type.
  7396. /// </summary>
  7397. public delegate void TypeMemberProvider(TypeNode/*!*/ type, object/*!*/ handle);
  7398. /// <summary>
  7399. /// A delegate that is called the first time NestedTypes is accessed, if non-null.
  7400. /// </summary>
  7401. public NestedTypeProvider ProvideNestedTypes;
  7402. /// <summary>
  7403. /// The type of delegates that fill in the NestedTypes property of the given type.
  7404. /// </summary>
  7405. public delegate void NestedTypeProvider(TypeNode/*!*/ type, object/*!*/ handle);
  7406. /// <summary>
  7407. /// A delegate that is called the first time Attributes is accessed, if non-null.
  7408. /// Provides for incremental construction of the type node.
  7409. /// Must not leave Attributes null.
  7410. /// </summary>
  7411. public TypeAttributeProvider ProvideTypeAttributes;
  7412. /// <summary>
  7413. /// The type of delegates that fill in the Attributes property of the given type.
  7414. /// </summary>
  7415. public delegate void TypeAttributeProvider(TypeNode/*!*/ type, object/*!*/ handle);
  7416. /// <summary>
  7417. /// Opaque information passed as a parameter to the delegates in ProvideTypeMembers et al.
  7418. /// Typically used to associate this namespace instance with a helper object.
  7419. /// </summary>
  7420. public object ProviderHandle;
  7421. private TypeNodeList templateInstances;
  7422. /// <summary>Contains all the types instantiated from this non generic template type.</summary>
  7423. public TypeNodeList TemplateInstances{
  7424. get{return this.templateInstances;}
  7425. set{this.templateInstances = value;}
  7426. }
  7427. internal TypeNode(NodeType nodeType)
  7428. : base(nodeType){
  7429. #if ExtendedRuntime
  7430. this.Contract = new TypeContract(this, true);
  7431. #endif
  7432. }
  7433. internal TypeNode(NodeType nodeType, NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  7434. : base(nodeType){
  7435. this.ProvideNestedTypes = provideNestedTypes;
  7436. this.ProvideTypeAttributes = provideAttributes;
  7437. this.ProvideTypeMembers = provideMembers;
  7438. this.ProviderHandle = handle;
  7439. #if !MinimalReader
  7440. this.isNormalized = true;
  7441. #endif
  7442. #if ExtendedRuntime
  7443. this.Contract = new TypeContract(this);
  7444. #endif
  7445. }
  7446. internal TypeNode(Module declaringModule, TypeNode declaringType, AttributeList attributes, TypeFlags flags,
  7447. Identifier Namespace, Identifier name, InterfaceList interfaces, MemberList members, NodeType nodeType)
  7448. : base(null, attributes, name, nodeType){
  7449. this.DeclaringModule = declaringModule;
  7450. this.DeclaringType = declaringType;
  7451. this.Flags = flags;
  7452. this.Interfaces = interfaces;
  7453. this.members = members;
  7454. this.Namespace = Namespace;
  7455. #if ExtendedRuntime
  7456. this.Contract = new TypeContract(this, true);
  7457. #endif
  7458. }
  7459. public override AttributeList Attributes{
  7460. get{
  7461. if (this.attributes == null){
  7462. if (this.ProvideTypeAttributes != null && this.ProviderHandle != null){
  7463. lock (Module.GlobalLock){
  7464. if (this.attributes == null)
  7465. this.ProvideTypeAttributes(this, this.ProviderHandle);
  7466. }
  7467. }else
  7468. this.attributes = new AttributeList(0);
  7469. }
  7470. return this.attributes;
  7471. }
  7472. set{
  7473. this.attributes = value;
  7474. }
  7475. }
  7476. protected SecurityAttributeList securityAttributes;
  7477. /// <summary>Contains declarative security information associated with the type.</summary>
  7478. public SecurityAttributeList SecurityAttributes{
  7479. get{
  7480. if (this.securityAttributes != null) return this.securityAttributes;
  7481. if (this.attributes == null){
  7482. AttributeList al = this.Attributes; //Getting the type attributes also gets the security attributes, in the case of a type that was read in by the Reader
  7483. if (al != null) al = null;
  7484. if (this.securityAttributes != null) return this.securityAttributes;
  7485. }
  7486. return this.securityAttributes = new SecurityAttributeList(0);
  7487. }
  7488. set{
  7489. this.securityAttributes = value;
  7490. }
  7491. }
  7492. /// <summary>The type from which this type is derived. Null in the case of interfaces and System.Object.</summary>
  7493. public virtual TypeNode BaseType{
  7494. get{
  7495. switch(this.NodeType){
  7496. case NodeType.ArrayType: return CoreSystemTypes.Array;
  7497. case NodeType.ClassParameter:
  7498. case NodeType.Class: return ((Class)this).BaseClass;
  7499. case NodeType.DelegateNode: return CoreSystemTypes.MulticastDelegate;
  7500. case NodeType.EnumNode: return CoreSystemTypes.Enum;
  7501. case NodeType.Struct:
  7502. #if !MinimalReader
  7503. case NodeType.TupleType:
  7504. case NodeType.TypeAlias:
  7505. case NodeType.TypeIntersection:
  7506. case NodeType.TypeUnion:
  7507. #endif
  7508. return CoreSystemTypes.ValueType;
  7509. default: return null;
  7510. }
  7511. }
  7512. }
  7513. protected internal MemberList defaultMembers;
  7514. /// <summary>A list of any members of this type that have the DefaultMember attribute.</summary>
  7515. public virtual MemberList DefaultMembers{
  7516. get{
  7517. int n = this.Members.Count;
  7518. if (n != this.memberCount){
  7519. this.UpdateMemberTable(n);
  7520. this.defaultMembers = null;
  7521. }
  7522. if (this.defaultMembers == null){
  7523. AttributeList attrs = this.Attributes;
  7524. Identifier defMemName = null;
  7525. for (int j = 0, m = attrs == null ? 0 : attrs.Count; j < m; j++){
  7526. //^ assert attrs != null;
  7527. AttributeNode attr = attrs[j];
  7528. if (attr == null) continue;
  7529. MemberBinding mb = attr.Constructor as MemberBinding;
  7530. if (mb != null && mb.BoundMember != null && mb.BoundMember.DeclaringType == SystemTypes.DefaultMemberAttribute){
  7531. if (attr.Expressions != null && attr.Expressions.Count > 0){
  7532. Literal lit = attr.Expressions[0] as Literal;
  7533. if (lit != null && lit.Value is string)
  7534. defMemName = Identifier.For((string)lit.Value);
  7535. }
  7536. break;
  7537. }
  7538. Literal litc = attr.Constructor as Literal;
  7539. if (litc != null && (litc.Value as TypeNode) == SystemTypes.DefaultMemberAttribute){
  7540. if (attr.Expressions != null && attr.Expressions.Count > 0){
  7541. Literal lit = attr.Expressions[0] as Literal;
  7542. if (lit != null && lit.Value is string)
  7543. defMemName = Identifier.For((string)lit.Value);
  7544. }
  7545. break;
  7546. }
  7547. }
  7548. if (defMemName != null)
  7549. this.defaultMembers = this.GetMembersNamed(defMemName);
  7550. else
  7551. this.defaultMembers = new MemberList(0);
  7552. }
  7553. return this.defaultMembers;
  7554. }
  7555. set{
  7556. this.defaultMembers = value;
  7557. }
  7558. }
  7559. protected string fullName;
  7560. public override string/*!*/ FullName {
  7561. get{
  7562. if (this.fullName != null) return this.fullName;
  7563. if (this.DeclaringType != null)
  7564. return this.fullName = this.DeclaringType.FullName+"+"+(this.Name == null ? "" : this.Name.ToString());
  7565. else if (this.Namespace != null && this.Namespace.UniqueIdKey != Identifier.Empty.UniqueIdKey)
  7566. return this.fullName = this.Namespace.ToString()+"."+(this.Name == null ? "" : this.Name.ToString());
  7567. else if (this.Name != null)
  7568. return this.fullName = this.Name.ToString();
  7569. else
  7570. return this.fullName = "";
  7571. }
  7572. }
  7573. #if !MinimalReader
  7574. // the same as FullName, except for dialects like Sing# with type extensions where names of
  7575. // type extensions may get mangled; in that case, this reports the name of the effective type node.
  7576. public virtual string FullNameDuringParsing {
  7577. get{ return this.FullName; }
  7578. }
  7579. #endif
  7580. public virtual string GetFullUnmangledNameWithoutTypeParameters(){
  7581. if (this.DeclaringType != null)
  7582. return this.DeclaringType.GetFullUnmangledNameWithoutTypeParameters()+"+"+this.GetUnmangledNameWithoutTypeParameters();
  7583. else if (this.Namespace != null && this.Namespace.UniqueIdKey != Identifier.Empty.UniqueIdKey)
  7584. return this.Namespace.ToString()+"."+this.GetUnmangledNameWithoutTypeParameters();
  7585. else
  7586. return this.GetUnmangledNameWithoutTypeParameters();
  7587. }
  7588. public virtual string GetFullUnmangledNameWithTypeParameters(){
  7589. if (this.DeclaringType != null)
  7590. return this.DeclaringType.GetFullUnmangledNameWithTypeParameters()+"+"+this.GetUnmangledNameWithTypeParameters(true);
  7591. else if (this.Namespace != null && this.Namespace.UniqueIdKey != Identifier.Empty.UniqueIdKey)
  7592. return this.Namespace.ToString()+"."+this.GetUnmangledNameWithTypeParameters(true);
  7593. else
  7594. return this.GetUnmangledNameWithTypeParameters(true);
  7595. }
  7596. public virtual string GetUnmangledNameWithTypeParameters(){
  7597. return this.GetUnmangledNameWithTypeParameters(false);
  7598. }
  7599. private string GetUnmangledNameWithTypeParameters(bool fullNamesForTypeParameters){
  7600. StringBuilder sb = new StringBuilder(this.GetUnmangledNameWithoutTypeParameters());
  7601. TypeNodeList templateParameters = this.TemplateParameters;
  7602. if (this.Template != null) templateParameters = this.TemplateArguments;
  7603. for (int i = 0, n = templateParameters == null ? 0 : templateParameters.Count; i < n; i++){
  7604. //^ assert templateParameters != null;
  7605. TypeNode tpar = templateParameters[i];
  7606. if (tpar == null) continue;
  7607. if (i == 0)
  7608. sb.Append('<');
  7609. else
  7610. sb.Append(',');
  7611. if (tpar.Name != null)
  7612. if (fullNamesForTypeParameters)
  7613. sb.Append(tpar.GetFullUnmangledNameWithTypeParameters());
  7614. else
  7615. sb.Append(tpar.GetUnmangledNameWithTypeParameters());
  7616. if (i == n-1)
  7617. sb.Append('>');
  7618. }
  7619. return sb.ToString();
  7620. }
  7621. protected static readonly char[]/*!*/ MangleChars = new char[]{'!', '>'};
  7622. public virtual string/*!*/ GetUnmangledNameWithoutTypeParameters(){
  7623. TypeNode.MangleChars[0] = TargetPlatform.GenericTypeNamesMangleChar;
  7624. if (this.Template != null) return this.Template.GetUnmangledNameWithoutTypeParameters();
  7625. if (this.Name == null) return "";
  7626. string name = this.Name.ToString();
  7627. if (this.TemplateParameters != null && this.TemplateParameters.Count > 0){
  7628. int lastMangle = name.LastIndexOfAny(TypeNode.MangleChars);
  7629. if (lastMangle >= 0){
  7630. if (name[lastMangle] == '>') lastMangle++;
  7631. return name.Substring(0, lastMangle);
  7632. }
  7633. }
  7634. return name;
  7635. }
  7636. #if !MinimalReader
  7637. public virtual string GetSerializedTypeName() {
  7638. bool isAssemblyQualified = true;
  7639. return this.GetSerializedTypeName(this, ref isAssemblyQualified);
  7640. }
  7641. string GetSerializedTypeName(TypeNode/*!*/ type, ref bool isAssemblyQualified) {
  7642. if (type == null) return null;
  7643. StringBuilder sb = new StringBuilder();
  7644. TypeModifier tMod = type as TypeModifier;
  7645. if (tMod != null)
  7646. type = tMod.ModifiedType;
  7647. ArrayType arrType = type as ArrayType;
  7648. if (arrType != null) {
  7649. type = arrType.ElementType;
  7650. bool isAssemQual = false;
  7651. this.AppendSerializedTypeName(sb, arrType.ElementType, ref isAssemQual);
  7652. if (arrType.IsSzArray())
  7653. sb.Append("[]");
  7654. else {
  7655. sb.Append('[');
  7656. if (arrType.Rank == 1) sb.Append('*');
  7657. for (int i = 1; i < arrType.Rank; i++) sb.Append(',');
  7658. sb.Append(']');
  7659. }
  7660. goto done;
  7661. }
  7662. Pointer pointer = type as Pointer;
  7663. if (pointer != null) {
  7664. type = pointer.ElementType;
  7665. bool isAssemQual = false;
  7666. this.AppendSerializedTypeName(sb, pointer.ElementType, ref isAssemQual);
  7667. sb.Append('*');
  7668. goto done;
  7669. }
  7670. Reference reference = type as Reference;
  7671. if (reference != null) {
  7672. type = reference.ElementType;
  7673. bool isAssemQual = false;
  7674. this.AppendSerializedTypeName(sb, reference.ElementType, ref isAssemQual);
  7675. sb.Append('&');
  7676. goto done;
  7677. }
  7678. if (type.Template == null)
  7679. sb.Append(type.FullName);
  7680. else {
  7681. sb.Append(type.Template.FullName);
  7682. sb.Append('[');
  7683. for (int i = 0, n = type.TemplateArguments == null ? 0 : type.TemplateArguments.Count; i < n; i++) {
  7684. //^ assert type.TemplateArguments != null;
  7685. bool isAssemQual = true;
  7686. this.AppendSerializedTypeName(sb, type.TemplateArguments[i], ref isAssemQual);
  7687. if (i < n-1) sb.Append(',');
  7688. }
  7689. sb.Append(']');
  7690. }
  7691. done:
  7692. if (isAssemblyQualified)
  7693. this.AppendAssemblyQualifierIfNecessary(sb, type, out isAssemblyQualified);
  7694. return sb.ToString();
  7695. }
  7696. void AppendAssemblyQualifierIfNecessary(StringBuilder/*!*/ sb, TypeNode type, out bool isAssemQualified) {
  7697. isAssemQualified = false;
  7698. if (type == null) return;
  7699. AssemblyNode referencedAssembly = type.DeclaringModule as AssemblyNode;
  7700. if (referencedAssembly != null) {
  7701. sb.Append(", ");
  7702. sb.Append(referencedAssembly.StrongName);
  7703. isAssemQualified = true;
  7704. }
  7705. }
  7706. void AppendSerializedTypeName(StringBuilder/*!*/ sb, TypeNode type, ref bool isAssemQualified) {
  7707. if (type == null) return;
  7708. string argTypeName = this.GetSerializedTypeName(type, ref isAssemQualified);
  7709. if (isAssemQualified) sb.Append('[');
  7710. sb.Append(argTypeName);
  7711. if (isAssemQualified) sb.Append(']');
  7712. }
  7713. #endif
  7714. /// <summary>
  7715. /// Return the name the constructor should have in this type node. By default, it's
  7716. /// the same as the name of the enclosing type node, but it can be different in e.g.
  7717. /// extensions in Extensible Sing#
  7718. /// </summary>
  7719. public virtual Identifier ConstructorName {
  7720. get {
  7721. if (this.constructorName == null) {
  7722. Identifier id = this.Name;
  7723. if (this.IsNormalized && this.IsGeneric)
  7724. id = Identifier.For(this.GetUnmangledNameWithoutTypeParameters());
  7725. this.constructorName = id;
  7726. }
  7727. return this.constructorName;
  7728. }
  7729. }
  7730. private Identifier constructorName;
  7731. /// <summary>True if the type is an abstract class or an interface.</summary>
  7732. public virtual bool IsAbstract{
  7733. get{
  7734. return (this.Flags & TypeFlags.Abstract) != 0;
  7735. }
  7736. }
  7737. public override bool IsAssembly{
  7738. get{
  7739. TypeFlags visibility = this.Flags & TypeFlags.VisibilityMask;
  7740. return visibility == TypeFlags.NotPublic || visibility == TypeFlags.NestedAssembly;
  7741. }
  7742. }
  7743. public override bool IsCompilerControlled{
  7744. get{return false;}
  7745. }
  7746. public override bool IsFamily{
  7747. get{return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedFamily;}
  7748. }
  7749. public override bool IsFamilyAndAssembly{
  7750. get{return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedFamANDAssem;}
  7751. }
  7752. public override bool IsFamilyOrAssembly{
  7753. get{return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedFamORAssem;}
  7754. }
  7755. protected bool isGeneric;
  7756. /// <summary>True if this type is a template conforming to the rules of a generic type in the CLR.</summary>
  7757. public virtual bool IsGeneric{
  7758. get{
  7759. return this.isGeneric;
  7760. }
  7761. set{
  7762. this.isGeneric = value;
  7763. }
  7764. }
  7765. #if ExtendedRuntime
  7766. public static bool IsImmutable(TypeNode type) {
  7767. type = TypeNode.StripModifiers(type);
  7768. if (type == null) return false;
  7769. if (type.TypeCode != TypeCode.Object) return true;
  7770. if (type.GetAttribute(SystemTypes.ImmutableAttribute) != null) return true;
  7771. if (type.IsValueType && type.DeclaringModule == CoreSystemTypes.SystemAssembly) return true; //hack.
  7772. return false;
  7773. }
  7774. #endif
  7775. public virtual bool IsNestedAssembly {
  7776. get{return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedAssembly;}
  7777. }
  7778. public virtual bool IsNestedFamily{
  7779. get{return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedFamily;}
  7780. }
  7781. public virtual bool IsNestedFamilyAndAssembly{
  7782. get{return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedFamANDAssem;}
  7783. }
  7784. public virtual bool IsNestedInternal{
  7785. get{return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedFamORAssem;}
  7786. }
  7787. public virtual bool IsNestedIn(TypeNode type){
  7788. for (TypeNode decType = this.DeclaringType; decType != null; decType = decType.DeclaringType){
  7789. if (decType == type) return true;
  7790. }
  7791. return false;
  7792. }
  7793. public virtual bool IsNestedPublic{
  7794. get{return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedPublic;}
  7795. }
  7796. public virtual bool IsNonPublic{
  7797. get{return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NotPublic;}
  7798. }
  7799. #if !MinimalReader
  7800. protected bool isNormalized;
  7801. /// <summary>
  7802. /// True if the type node is in "normal" form. A node is in "normal" form if it is effectively a node in an AST formed directly
  7803. /// from CLR module or assembly. Such a node can be written out as compiled code to an assembly or module without further processing.
  7804. /// </summary>
  7805. public virtual bool IsNormalized{
  7806. get{
  7807. if (this.isNormalized) return true;
  7808. if (this.DeclaringModule == null) return false;
  7809. return this.isNormalized = this.DeclaringModule.IsNormalized;
  7810. }
  7811. set{
  7812. this.isNormalized = value;
  7813. }
  7814. }
  7815. #endif
  7816. public override bool IsPrivate{
  7817. get{return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedPrivate;}
  7818. }
  7819. /// <summary>True if values of this type can be compared directly in CLR IL instructions.</summary>
  7820. public virtual bool IsPrimitiveComparable{
  7821. get{
  7822. switch(this.typeCode){
  7823. case ElementType.Boolean:
  7824. case ElementType.Char:
  7825. case ElementType.Int8:
  7826. case ElementType.Int16:
  7827. case ElementType.Int32:
  7828. case ElementType.Int64:
  7829. case ElementType.IntPtr:
  7830. case ElementType.UInt8:
  7831. case ElementType.UInt16:
  7832. case ElementType.UInt32:
  7833. case ElementType.UInt64:
  7834. case ElementType.UIntPtr:
  7835. case ElementType.Single:
  7836. case ElementType.Double:
  7837. return true;
  7838. default:
  7839. return !(this is Struct) || this is EnumNode || this is Pointer;
  7840. }
  7841. }
  7842. }
  7843. /// <summary>True if values of this type are integers that can be processed by CLR IL instructions.</summary>
  7844. public virtual bool IsPrimitiveInteger{
  7845. get{
  7846. switch(this.typeCode){
  7847. case ElementType.Int8:
  7848. case ElementType.Int16:
  7849. case ElementType.Int32:
  7850. case ElementType.Int64:
  7851. case ElementType.IntPtr:
  7852. case ElementType.UInt8:
  7853. case ElementType.UInt16:
  7854. case ElementType.UInt32:
  7855. case ElementType.UInt64:
  7856. case ElementType.UIntPtr:
  7857. return true;
  7858. default:
  7859. return false;
  7860. }
  7861. }
  7862. }
  7863. /// <summary>True if values of this type are integers or floating point numbers that can be processed by CLR IL instructions.</summary>
  7864. public virtual bool IsPrimitiveNumeric{
  7865. get{
  7866. switch(this.typeCode){
  7867. case ElementType.Int8:
  7868. case ElementType.Int16:
  7869. case ElementType.Int32:
  7870. case ElementType.Int64:
  7871. case ElementType.IntPtr:
  7872. case ElementType.UInt8:
  7873. case ElementType.UInt16:
  7874. case ElementType.UInt32:
  7875. case ElementType.UInt64:
  7876. case ElementType.UIntPtr:
  7877. case ElementType.Single:
  7878. case ElementType.Double:
  7879. return true;
  7880. default:
  7881. return false;
  7882. }
  7883. }
  7884. }
  7885. /// <summary>True if values of this type are unsigned integers that can be processed by CLR IL instructions.</summary>
  7886. public virtual bool IsPrimitiveUnsignedInteger {
  7887. get {
  7888. switch (this.typeCode) {
  7889. case ElementType.UInt8:
  7890. case ElementType.UInt16:
  7891. case ElementType.UInt32:
  7892. case ElementType.UInt64:
  7893. case ElementType.UIntPtr:
  7894. return true;
  7895. default:
  7896. return false;
  7897. }
  7898. }
  7899. }
  7900. public override bool IsPublic {
  7901. get{
  7902. TypeFlags visibility = this.Flags & TypeFlags.VisibilityMask;
  7903. return visibility == TypeFlags.Public || visibility == TypeFlags.NestedPublic;
  7904. }
  7905. }
  7906. /// <summary>True if values of this type can be processed by CLR IL instructions.</summary>
  7907. public virtual bool IsPrimitive{
  7908. get{
  7909. switch(this.typeCode){
  7910. case ElementType.Boolean:
  7911. case ElementType.Char:
  7912. case ElementType.Double:
  7913. case ElementType.Int16:
  7914. case ElementType.Int32:
  7915. case ElementType.Int64:
  7916. case ElementType.Int8:
  7917. case ElementType.IntPtr:
  7918. case ElementType.Single:
  7919. case ElementType.String:
  7920. case ElementType.UInt16:
  7921. case ElementType.UInt32:
  7922. case ElementType.UInt64:
  7923. case ElementType.UInt8:
  7924. case ElementType.UIntPtr:
  7925. return true;
  7926. default:
  7927. return false;
  7928. }
  7929. }
  7930. }
  7931. /// <summary>True if the type cannot be derived from.</summary>
  7932. public virtual bool IsSealed{
  7933. get{
  7934. return (this.Flags & TypeFlags.Sealed) != 0;
  7935. }
  7936. }
  7937. public override bool IsSpecialName{
  7938. get{return (this.Flags & TypeFlags.SpecialName) != 0;}
  7939. }
  7940. public override bool IsStatic{
  7941. get{return true;}
  7942. }
  7943. /// <summary>True if the identity of the type depends on its structure rather than its name.
  7944. /// Arrays, pointers and generic type instances are examples of such types.</summary>
  7945. public virtual bool IsStructural{
  7946. get{
  7947. return this.Template != null;
  7948. }
  7949. }
  7950. /// <summary>True if the type serves as a parameter to a type template.</summary>
  7951. public virtual bool IsTemplateParameter{
  7952. get{
  7953. return false;
  7954. }
  7955. }
  7956. /// <summary>True if the type is a value type containing only fields of unmanaged types.</summary>
  7957. public virtual bool IsUnmanaged{
  7958. get{
  7959. #if ExtendedRuntime
  7960. return IsPointerFree;
  7961. #else
  7962. return false;
  7963. #endif
  7964. }
  7965. }
  7966. /// <summary>A list of the types that contribute to the structure of a structural type.</summary>
  7967. public virtual TypeNodeList StructuralElementTypes{
  7968. get{
  7969. TypeNodeList result = this.TemplateArguments;
  7970. if (result != null && result.Count > 0) return result;
  7971. return this.TemplateParameters;
  7972. }
  7973. }
  7974. /// <summary>True if values of this type are unsigned integers that can be processed by CLR IL instructions.</summary>
  7975. public virtual bool IsUnsignedPrimitiveNumeric{
  7976. get{
  7977. switch(this.typeCode){
  7978. case ElementType.UInt8:
  7979. case ElementType.UInt16:
  7980. case ElementType.UInt32:
  7981. case ElementType.UInt64:
  7982. case ElementType.UIntPtr:
  7983. return true;
  7984. default:
  7985. return false;
  7986. }
  7987. }
  7988. }
  7989. /// <summary>True if instances of this type have no identity other than their value and are copied upon assignment.</summary>
  7990. public virtual bool IsValueType{
  7991. get{
  7992. switch(this.NodeType){
  7993. case NodeType.EnumNode:
  7994. #if !MinimalReader
  7995. case NodeType.ConstrainedType:
  7996. case NodeType.TupleType:
  7997. case NodeType.TypeAlias:
  7998. case NodeType.TypeIntersection:
  7999. case NodeType.TypeUnion: return true;
  8000. #endif
  8001. case NodeType.Struct: return true;
  8002. default: return false;
  8003. }
  8004. }
  8005. }
  8006. #if ExtendedRuntime
  8007. /// <summary>True if the type is a value type containing no managed or unmanaged pointers.</summary>
  8008. public virtual bool IsPointerFree
  8009. {
  8010. get
  8011. {
  8012. return false;
  8013. }
  8014. }
  8015. /// <summary>
  8016. /// Returns true if the type is definitely a reference type.
  8017. /// </summary>
  8018. public virtual bool IsReferenceType {
  8019. get {
  8020. switch (this.NodeType) {
  8021. case NodeType.Class:
  8022. case NodeType.Interface:
  8023. case NodeType.Pointer:
  8024. case NodeType.ArrayType:
  8025. case NodeType.DelegateNode:
  8026. return this != SystemTypes.ValueType && this != SystemTypes.Enum;
  8027. default:
  8028. return false;
  8029. }
  8030. }
  8031. }
  8032. #endif
  8033. /// <summary>
  8034. /// True if underlying type (modulo type modifiers) is a pointer type (Pointer)
  8035. /// </summary>
  8036. public virtual bool IsPointerType{
  8037. get { return false; }
  8038. }
  8039. public override bool IsVisibleOutsideAssembly{
  8040. get{
  8041. if (this.DeclaringType != null && !this.DeclaringType.IsVisibleOutsideAssembly) return false;
  8042. switch(this.Flags & TypeFlags.VisibilityMask){
  8043. case TypeFlags.Public:
  8044. case TypeFlags.NestedPublic:
  8045. return true;
  8046. case TypeFlags.NestedFamily:
  8047. case TypeFlags.NestedFamORAssem:
  8048. return this.DeclaringType != null && !this.DeclaringType.IsSealed;
  8049. default:
  8050. return false;
  8051. }
  8052. }
  8053. }
  8054. // This field stores those members declared syntactically within
  8055. // this type node. (Under Extended Sing#, additional members can
  8056. // be logically part of a type node but declared in a separate
  8057. // syntactic type node.)
  8058. protected internal MemberList members;
  8059. protected volatile internal bool membersBeingPopulated;
  8060. /// <summary>
  8061. /// The list of members contained inside this type, by default ignoring any extensions of this type.
  8062. /// (Subclasses in the Extensible Sing# dialect override this to include members of visible extensions.)
  8063. /// If the value of members is null and the value of ProvideTypeMembers is not null, the
  8064. /// TypeMemberProvider delegate is called to fill in the value of this property.
  8065. /// </summary>
  8066. public virtual MemberList Members{
  8067. get{
  8068. if (this.members == null || this.membersBeingPopulated)
  8069. if (this.ProvideTypeMembers != null && this.ProviderHandle != null){
  8070. lock (Module.GlobalLock){
  8071. if (this.members == null){
  8072. this.membersBeingPopulated = true;
  8073. this.ProvideTypeMembers(this, this.ProviderHandle);
  8074. this.membersBeingPopulated = false;
  8075. #if ExtendedRuntime
  8076. this.ApplyOutOfBandContracts();
  8077. #endif
  8078. }
  8079. }
  8080. }else
  8081. this.members = new MemberList();
  8082. return this.members;
  8083. }
  8084. set{
  8085. this.members = value;
  8086. this.memberCount = 0;
  8087. this.memberTable = null;
  8088. this.constructors = null;
  8089. this.defaultMembers = null;
  8090. #if !MinimalReader
  8091. this.explicitCoercionFromTable = null;
  8092. this.explicitCoercionMethods = null;
  8093. this.explicitCoercionToTable = null;
  8094. this.implicitCoercionFromTable = null;
  8095. this.implicitCoercionMethods = null;
  8096. this.implicitCoercionToTable = null;
  8097. this.opFalse = null;
  8098. this.opTrue = null;
  8099. #endif
  8100. }
  8101. }
  8102. #if ExtendedRuntime
  8103. protected internal TypeNode ContractType
  8104. {
  8105. get
  8106. {
  8107. AssemblyNode declaringAssembly = this.DeclaringModule as AssemblyNode;
  8108. if (declaringAssembly == null || declaringAssembly.ContractAssembly == null) return null;
  8109. if (this.DeclaringType == null)
  8110. {
  8111. return declaringAssembly.ContractAssembly.GetType(this.Namespace, this.Name);
  8112. }
  8113. else
  8114. {
  8115. TypeNode parentContractType = this.DeclaringType.ContractType;
  8116. if (parentContractType == null) return null;
  8117. return parentContractType.GetNestedType(this.Name);
  8118. }
  8119. }
  8120. }
  8121. protected internal virtual void ApplyOutOfBandContracts(){
  8122. if (this.members == null) return;
  8123. TypeNode contractType = this.ContractType;
  8124. if (contractType == null) return;
  8125. // Copy the type-level contract attributes over to the shadowed type, namely "this".
  8126. int contractsNamespaceKey = SystemTypes.NonNullType.Namespace.UniqueIdKey;
  8127. foreach (AttributeNode attr in contractType.Attributes) {
  8128. if (attr.Type.Namespace != null && attr.Type.Namespace.UniqueIdKey == contractsNamespaceKey)
  8129. this.Attributes.Add(attr);
  8130. }
  8131. if (this.BaseType != null) { MemberList junk = this.BaseType.Members; if (junk != null) junk = null; }
  8132. Hashtable contractByFullName = new Hashtable();
  8133. MemberList contractMembers = contractType.Members;
  8134. for (int i = 0, n = contractMembers == null ? 0 : contractMembers.Count; i < n; i++){
  8135. //^ assert contractMembers != null;
  8136. Field f = contractMembers[i] as Field;
  8137. if (f != null) {
  8138. contractByFullName[f.FullName] = f;
  8139. continue;
  8140. }
  8141. Method m = contractMembers[i] as Method;
  8142. if (m == null ) continue;
  8143. string methName = this.FullStrippedName(m);
  8144. contractByFullName[methName] = m;
  8145. }
  8146. for (int i = 0, n = members.Count; i < n; i++){
  8147. Field codeField = members[i] as Field;
  8148. if (codeField != null) {
  8149. Field contractField = contractByFullName[codeField.FullName] as Field;
  8150. if (contractField != null && contractField.Type != null && contractField.Type != codeField.Type) {
  8151. OptionalModifier optFieldType = contractField.Type as OptionalModifier;
  8152. if (optFieldType != null && codeField.Type != null) {
  8153. codeField.Type = OptionalModifier.For(optFieldType.Modifier, codeField.Type);
  8154. codeField.HasOutOfBandContract = true;
  8155. }
  8156. }
  8157. continue;
  8158. }
  8159. Method codeMethod = members[i] as Method;
  8160. if (codeMethod == null) continue;
  8161. // we include the return type since some conversion operators result
  8162. // in overloaded methods whose signatures differ only in return type
  8163. string methName = this.FullStrippedName(codeMethod);
  8164. Method contractMethod = contractByFullName[methName] as Method;
  8165. if (contractMethod != null) {
  8166. this.CopyContractToMethod(contractMethod, codeMethod);
  8167. if (codeMethod.OverridesBaseClassMember) {
  8168. Method overridden = this.FindNearestOverriddenMethod(contractMethod);
  8169. if (overridden != null)
  8170. this.CopyContractToMethod(overridden, codeMethod);
  8171. }
  8172. } else {
  8173. // Maybe there isn't a shadow method declared in contractType, but
  8174. // there still might be out-of-band contracts on an interface method
  8175. // that the codeMethod implements.
  8176. if (codeMethod.ImplementedInterfaceMethods != null && codeMethod.ImplementedInterfaceMethods.Count > 0) {
  8177. foreach (Method m in codeMethod.ImplementedInterfaceMethods) {
  8178. this.CopyContractToMethod(m, codeMethod);
  8179. }
  8180. } else if (codeMethod.ImplicitlyImplementedInterfaceMethods != null) {
  8181. foreach (Method m in codeMethod.ImplicitlyImplementedInterfaceMethods) {
  8182. this.CopyContractToMethod(m, codeMethod);
  8183. }
  8184. }
  8185. }
  8186. }
  8187. }
  8188. protected virtual string/*!*/ FullStrippedName(Method/*!*/ m) {
  8189. StringBuilder sb = new StringBuilder();
  8190. sb.Append(m.DeclaringType.GetFullUnmangledNameWithTypeParameters());
  8191. sb.Append('.');
  8192. if (m.NodeType == NodeType.InstanceInitializer)
  8193. sb.Append("#ctor");
  8194. else if (m.Name != null)
  8195. sb.Append(m.Name.ToString());
  8196. ParameterList parameters = m.Parameters;
  8197. for (int i = 0, n = parameters == null ? 0 : parameters.Count; i < n; i++){
  8198. Parameter par = parameters[i];
  8199. if (par == null || par.Type == null) continue;
  8200. TypeNode parType = TypeNode.DeepStripModifiers(par.Type);
  8201. Reference rt = parType as Reference;
  8202. if (rt != null && rt.ElementType != null)
  8203. parType = TypeNode.DeepStripModifiers(rt.ElementType).GetReferenceType();
  8204. //^ assert parType != null;
  8205. if (i == 0)
  8206. sb.Append('(');
  8207. else
  8208. sb.Append(',');
  8209. sb.Append(parType.GetFullUnmangledNameWithTypeParameters());
  8210. if (i == n-1)
  8211. sb.Append(')');
  8212. }
  8213. if (m.ReturnType != null){
  8214. TypeNode retType = TypeNode.DeepStripModifiers(m.ReturnType);
  8215. //^ assert retType != null;
  8216. sb.Append(retType.GetFullUnmangledNameWithTypeParameters());
  8217. }
  8218. return sb.ToString();
  8219. }
  8220. protected virtual void CopyContractToMethod(Method/*!*/ contractMethod, Method/*!*/ codeMethod) {
  8221. codeMethod.HasOutOfBandContract = true;
  8222. if (codeMethod.Contract == null)
  8223. codeMethod.Contract = new MethodContract(codeMethod);
  8224. // setting them to null forces deserialization upon next access to the property
  8225. // NB: This means that out-of-band contracts can be applied *only* to code that
  8226. // does *not* have any contracts since this will wipe them out!!
  8227. codeMethod.Contract.Ensures = null;
  8228. codeMethod.Contract.Modifies = null;
  8229. codeMethod.Contract.Requires = null;
  8230. int contractsNamespaceKey = SystemTypes.NonNullType.Namespace.UniqueIdKey;
  8231. // Copy the method-level contract attributes over to the shadowed method.
  8232. for (int a = 0; a < contractMethod.Attributes.Count; a++){
  8233. AttributeNode attr = contractMethod.Attributes[a];
  8234. if (attr != null && attr.Type != null && attr.Type.Namespace != null &&
  8235. attr.Type.Namespace != null && attr.Type.Namespace.UniqueIdKey == contractsNamespaceKey)
  8236. codeMethod.Attributes.Add(attr);
  8237. }
  8238. // Copy over any return attributes to the shadowed method
  8239. for (int a = 0, n = contractMethod.ReturnAttributes == null ? 0 : contractMethod.ReturnAttributes.Count; a < n; a++) {
  8240. AttributeNode attr = contractMethod.ReturnAttributes[a];
  8241. if (attr != null) {
  8242. if (attr.Type.Namespace != null && attr.Type.Namespace.UniqueIdKey == contractsNamespaceKey) {
  8243. if (codeMethod.ReturnAttributes == null) {
  8244. codeMethod.ReturnAttributes = new AttributeList();
  8245. }
  8246. codeMethod.ReturnAttributes.Add(attr);
  8247. }
  8248. }
  8249. }
  8250. // Copy the parameter-level contract attributes and type over to the shadowed method's parameters.
  8251. ParameterList contractParameters = contractMethod.Parameters;
  8252. ParameterList codeParameters = codeMethod.Parameters;
  8253. if (contractParameters != null && codeParameters != null && contractParameters.Count <= codeParameters.Count) {
  8254. for (int i = 0, n = contractParameters.Count; i < n; i++) {
  8255. Parameter contractParameter = contractParameters[i];
  8256. Parameter codeParameter = codeParameters[i];
  8257. if (contractParameter == null || codeParameter == null) continue;
  8258. for (int a = 0, m = contractParameter.Attributes == null ? 0 : contractParameter.Attributes.Count; a < m; a++){
  8259. //^ assert contractParameter.Attributes != null;
  8260. AttributeNode attr = contractParameter.Attributes[a];
  8261. if (attr == null || attr.Type == null) continue;
  8262. if (attr.Type.Namespace != null && attr.Type.Namespace.UniqueIdKey == contractsNamespaceKey){
  8263. if (codeParameter.Attributes == null) codeParameter.Attributes = new AttributeList();
  8264. codeParameter.Attributes.Add(attr);
  8265. }
  8266. }
  8267. if (contractParameter.Type != codeParameter.Type)
  8268. codeParameter.Type = this.CopyModifier(contractParameter.Type, codeParameter.Type);
  8269. }
  8270. }
  8271. if (contractMethod.ReturnType != codeMethod.ReturnType)
  8272. codeMethod.ReturnType = this.CopyModifier(contractMethod.ReturnType, codeMethod.ReturnType);
  8273. codeMethod.fullName = null;
  8274. }
  8275. private TypeNode CopyModifier(TypeNode contractType, TypeNode codeType) {
  8276. if (contractType == null) return codeType;
  8277. Reference rcType = contractType as Reference;
  8278. if (rcType != null) {
  8279. contractType = rcType.ElementType;
  8280. if (contractType == null) return codeType;
  8281. Reference rcodeType = codeType as Reference;
  8282. if (rcodeType == null || rcodeType.ElementType == null) return codeType;
  8283. TypeNode t = CopyModifier(contractType, rcodeType.ElementType);
  8284. return t.GetReferenceType();
  8285. }
  8286. ArrayType acType = contractType as ArrayType;
  8287. if (acType != null) {
  8288. contractType = acType.ElementType;
  8289. if (contractType == null) return codeType;
  8290. ArrayType acodeType = codeType as ArrayType;
  8291. if (acodeType == null || acodeType.ElementType == null) return codeType;
  8292. TypeNode t = CopyModifier(contractType, acodeType.ElementType);
  8293. return t.GetArrayType(1);
  8294. }
  8295. OptionalModifier optModType = contractType as OptionalModifier;
  8296. if (optModType != null && optModType.Modifier != null) {
  8297. TypeNode t = CopyModifier(optModType.ModifiedType, codeType);
  8298. codeType = OptionalModifier.For(optModType.Modifier, t);
  8299. }
  8300. if (contractType.Template != null && codeType.Template != null && contractType.TemplateArguments != null && codeType.TemplateArguments != null) {
  8301. TypeNodeList args = contractType.TemplateArguments.Clone();
  8302. TypeNodeList codeArgs = codeType.TemplateArguments;
  8303. for (int i = 0, n = args.Count, m = codeArgs.Count; i < n && i < m; i++) {
  8304. TypeNode argType = args[i];
  8305. TypeNode codeArgType = codeArgs[i];
  8306. if (argType != codeArgType)
  8307. args[i] = this.CopyModifier(argType, codeArgType);
  8308. }
  8309. return codeType.Template.GetTemplateInstance(codeType, args);
  8310. }
  8311. return codeType;
  8312. }
  8313. public virtual Method FindNearestOverriddenMethod (Method method)
  8314. //^ requires method.IsVirtual;
  8315. {
  8316. if (method == null) return null;
  8317. if (!method.IsVirtual) return null;
  8318. int numParams = method.Parameters == null ? 0 : method.Parameters.Count;
  8319. TypeNode[] paramTypes = new TypeNode[numParams];
  8320. for (int i=0; i<numParams; i++) paramTypes[i] = method.Parameters[i].Type;
  8321. for (TypeNode scan = method.DeclaringType.BaseType; scan != null; scan = scan.BaseType){
  8322. Method overridden = scan.GetMethod(method.Name, paramTypes);
  8323. if (overridden != null) return overridden;
  8324. }
  8325. return null;
  8326. }
  8327. public TypeNodeList ReferencedTemplateInstances;
  8328. #endif
  8329. protected TypeNode template;
  8330. /// <summary>The (generic) type template from which this type was instantiated. Null if this is not a (generic) type template instance.</summary>
  8331. public virtual TypeNode Template{
  8332. get{
  8333. TypeNode result = this.template;
  8334. if (result == null){
  8335. if (this.isGeneric || TargetPlatform.GenericTypeNamesMangleChar != '_') return null;
  8336. AttributeList attributes = this.Attributes;
  8337. lock(this){
  8338. if (this.template != null){
  8339. if (this.template == TypeNode.NotSpecified)
  8340. return null;
  8341. return this.template;
  8342. }
  8343. #if ExtendedRuntime
  8344. for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++) {
  8345. AttributeNode attr = attributes[i];
  8346. if (attr == null) continue;
  8347. MemberBinding mb = attr.Constructor as MemberBinding;
  8348. if (mb == null || mb.BoundMember == null || mb.BoundMember.DeclaringType != SystemTypes.TemplateInstanceAttribute) continue;
  8349. ExpressionList exprs = attr.Expressions;
  8350. if (exprs == null || exprs.Count != 2) continue;
  8351. Literal lit = exprs[0] as Literal;
  8352. if (lit == null) continue;
  8353. TypeNode templ = lit.Value as TypeNode;
  8354. if (templ != null) {
  8355. lit = exprs[1] as Literal;
  8356. if (lit == null) continue;
  8357. object[] types = lit.Value as object[];
  8358. if (types == null) continue;
  8359. int m = types == null ? 0 : types.Length;
  8360. TypeNodeList templateArguments = new TypeNodeList(m);
  8361. for (int j = 0; j < m; j++) {
  8362. TypeNode t = types[j] as TypeNode;
  8363. if (t == null) continue;
  8364. templateArguments.Add(t);
  8365. }
  8366. this.TemplateArguments = templateArguments;
  8367. return this.template = templ;
  8368. }
  8369. }
  8370. #endif
  8371. if (result == null)
  8372. this.template = TypeNode.NotSpecified;
  8373. }
  8374. }else if (result == TypeNode.NotSpecified)
  8375. return null;
  8376. return result;
  8377. }
  8378. set{
  8379. this.template = value;
  8380. }
  8381. }
  8382. #if !MinimalReader
  8383. public TypeNode TemplateExpression;
  8384. #endif
  8385. protected TypeNodeList templateArguments;
  8386. /// <summary>The arguments used when this (generic) type template instance was instantiated.</summary>
  8387. public virtual TypeNodeList TemplateArguments{
  8388. get{
  8389. if (this.template == null){
  8390. TypeNode templ = this.Template; //Will fill in the arguments
  8391. if (templ != null) templ = null;
  8392. }
  8393. return this.templateArguments;
  8394. }
  8395. set{
  8396. this.templateArguments = value;
  8397. }
  8398. }
  8399. #if !MinimalReader
  8400. public TypeNodeList TemplateArgumentExpressions;
  8401. #endif
  8402. internal TypeNodeList consolidatedTemplateArguments;
  8403. public virtual TypeNodeList ConsolidatedTemplateArguments{
  8404. get{
  8405. if (this.consolidatedTemplateArguments == null)
  8406. this.consolidatedTemplateArguments = this.GetConsolidatedTemplateArguments();
  8407. return this.consolidatedTemplateArguments;
  8408. }
  8409. set{
  8410. this.consolidatedTemplateArguments = value;
  8411. }
  8412. }
  8413. private void AddTemplateParametersFromAttributeEncoding(TypeNodeList result)
  8414. {
  8415. #if ExtendedRuntime
  8416. if (result.Count == 0) {
  8417. AttributeList attributes = this.Attributes;
  8418. for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++) {
  8419. AttributeNode attr = attributes[i];
  8420. if (attr == null) continue;
  8421. MemberBinding mb = attr.Constructor as MemberBinding;
  8422. if (mb == null || mb.BoundMember == null || mb.BoundMember.DeclaringType != SystemTypes.TemplateAttribute) continue;
  8423. ExpressionList exprs = attr.Expressions;
  8424. if (exprs == null || exprs.Count != 1) continue;
  8425. Literal lit = exprs[0] as Literal;
  8426. if (lit == null) continue;
  8427. object[] types = lit.Value as object[];
  8428. if (types == null) continue;
  8429. for (int j = 0, m = types == null ? 0 : types.Length; j < m; j++) {
  8430. TypeNode t = types[j] as TypeNode;
  8431. if (t == null) continue;
  8432. if (t.NodeType == NodeType.TypeParameter || t.NodeType == NodeType.ClassParameter)
  8433. result.Add(t);
  8434. }
  8435. attributes[i] = null;
  8436. }
  8437. }
  8438. #endif
  8439. }
  8440. internal TypeNodeList templateParameters;
  8441. /// <summary>The type parameters of this type. Null if this type is not a (generic) type template.</summary>
  8442. public virtual TypeNodeList TemplateParameters{
  8443. get{
  8444. TypeNodeList result = this.templateParameters;
  8445. if (result == null){
  8446. if (this.isGeneric || TargetPlatform.GenericTypeNamesMangleChar != '_') return null; //Can happen when this is nested in a generic type
  8447. TypeNodeList nestedTypes = this.NestedTypes;
  8448. lock (this) {
  8449. if ((result = this.templateParameters) != null) return result.Count == 0 ? null : result;
  8450. result = new TypeNodeList();
  8451. for (int i = 0, n = nestedTypes == null ? 0 : nestedTypes.Count; i < n; i++) {
  8452. TypeNode nt = nestedTypes[i];
  8453. if (nt == null) continue;
  8454. if (nt is MethodTypeParameter) continue;
  8455. if (nt.NodeType == NodeType.TypeParameter || nt.NodeType == NodeType.ClassParameter)
  8456. result.Add(nt);
  8457. }
  8458. this.AddTemplateParametersFromAttributeEncoding(result);
  8459. this.TemplateParameters = result;
  8460. }
  8461. }
  8462. if (result.Count == 0) return null;
  8463. return result;
  8464. }
  8465. set{
  8466. if (value == null){
  8467. if (this.templateParameters == null) return;
  8468. if (this.templateParameters.Count > 0)
  8469. value = new TypeNodeList(0);
  8470. }
  8471. this.templateParameters = value;
  8472. }
  8473. }
  8474. protected internal TypeNodeList consolidatedTemplateParameters;
  8475. public virtual TypeNodeList ConsolidatedTemplateParameters{
  8476. get{
  8477. if (this.consolidatedTemplateParameters == null)
  8478. this.consolidatedTemplateParameters = this.GetConsolidatedTemplateParameters();
  8479. return this.consolidatedTemplateParameters;
  8480. }
  8481. set{
  8482. this.consolidatedTemplateParameters = value;
  8483. }
  8484. }
  8485. internal ElementType typeCode = ElementType.Class;
  8486. /// <summary>The System.TypeCode value that Convert.GetTypeCode will return pass an instance of this type as parameter.</summary>
  8487. public virtual System.TypeCode TypeCode{
  8488. get{
  8489. switch(this.typeCode){
  8490. case ElementType.Boolean : return System.TypeCode.Boolean;
  8491. case ElementType.Char : return System.TypeCode.Char;
  8492. case ElementType.Double : return System.TypeCode.Double;
  8493. case ElementType.Int16 : return System.TypeCode.Int16;
  8494. case ElementType.Int32 : return System.TypeCode.Int32;
  8495. case ElementType.Int64 : return System.TypeCode.Int64;
  8496. case ElementType.Int8 : return System.TypeCode.SByte;
  8497. case ElementType.Single : return System.TypeCode.Single;
  8498. case ElementType.UInt16 : return System.TypeCode.UInt16;
  8499. case ElementType.UInt32 : return System.TypeCode.UInt32;
  8500. case ElementType.UInt64 : return System.TypeCode.UInt64;
  8501. case ElementType.UInt8 : return System.TypeCode.Byte;
  8502. case ElementType.Void : return System.TypeCode.Empty;
  8503. default:
  8504. if (this == CoreSystemTypes.String) return System.TypeCode.String;
  8505. #if !MinimalReader
  8506. if (this == CoreSystemTypes.Decimal) return System.TypeCode.Decimal;
  8507. if (this == CoreSystemTypes.DateTime) return System.TypeCode.DateTime;
  8508. if (this == CoreSystemTypes.DBNull) return System.TypeCode.DBNull;
  8509. #endif
  8510. return System.TypeCode.Object;
  8511. }
  8512. }
  8513. }
  8514. private readonly static TypeNode NotSpecified = new Class();
  8515. #if !FxCop
  8516. protected
  8517. #endif
  8518. internal TrivialHashtableUsingWeakReferences structurallyEquivalentMethod;
  8519. #if !MinimalReader
  8520. /// <summary>
  8521. /// Returns the methods of an abstract type that have been left unimplemented. Includes methods inherited from
  8522. /// base classes and interfaces, and methods from any (known) extensions.
  8523. /// </summary>
  8524. /// <param name="result">A method list to which the abstract methods must be appended.</param>
  8525. public virtual void GetAbstractMethods(MethodList/*!*/ result) {
  8526. if (!this.IsAbstract) return;
  8527. //For each interface, get abstract methods and keep those that are not implemented by this class or a base class
  8528. InterfaceList interfaces = this.Interfaces;
  8529. for (int i = 0, n = interfaces == null ? 0 : interfaces.Count; i < n; i++){
  8530. Interface iface = interfaces[i];
  8531. if (iface == null) continue;
  8532. MemberList imembers = iface.Members;
  8533. for (int j = 0, m = imembers == null ? 0 : imembers.Count; j < m; j++){
  8534. Method meth = imembers[j] as Method;
  8535. if (meth == null) continue;
  8536. if (this.ImplementsExplicitly(meth)) continue;
  8537. if (this.ImplementsMethod(meth, true)) continue;
  8538. result.Add(meth);
  8539. }
  8540. }
  8541. }
  8542. #endif
  8543. protected internal TrivialHashtable szArrayTypes;
  8544. /// <summary>
  8545. /// Returns a type representing an array whose elements are of this type. Will always return the same instance for the same rank.
  8546. /// </summary>
  8547. /// <param name="rank">The number of dimensions of the array.</param>
  8548. public virtual ArrayType/*!*/ GetArrayType(int rank) {
  8549. return this.GetArrayType(rank, false);
  8550. }
  8551. public virtual ArrayType/*!*/ GetArrayType(int rank, bool lowerBoundIsUnknown) {
  8552. if (rank > 1 || lowerBoundIsUnknown) return this.GetArrayType(rank, 0, 0, new int[0], new int[0]);
  8553. if (this.szArrayTypes == null) this.szArrayTypes = new TrivialHashtable();
  8554. ArrayType result = (ArrayType)this.szArrayTypes[rank];
  8555. if (result != null) return result;
  8556. lock(this){
  8557. result = (ArrayType)this.szArrayTypes[rank];
  8558. if (result != null) return result;
  8559. this.szArrayTypes[rank] = result = new ArrayType(this, 1);
  8560. result.Flags &= ~TypeFlags.VisibilityMask;
  8561. result.Flags |= this.Flags & TypeFlags.VisibilityMask;
  8562. return result;
  8563. }
  8564. }
  8565. protected internal TrivialHashtable arrayTypes;
  8566. /// <summary>
  8567. /// Returns a type representing an array whose elements are of this type. Will always return the same instance for the same rank, sizes and bounds.
  8568. /// </summary>
  8569. /// <param name="rank">The number of dimensions of the array.</param>
  8570. /// <param name="sizes">The size of each dimension.</param>
  8571. /// <param name="loBounds">The lower bound for indices. Defaults to zero.</param>
  8572. public virtual ArrayType/*!*/ GetArrayType(int rank, int[] sizes, int[] loBounds) {
  8573. return this.GetArrayType(rank, sizes == null ? 0 : sizes.Length, loBounds == null ? 0 : loBounds.Length, sizes == null ? new int[0] : sizes, loBounds == null ? new int[0] : loBounds);
  8574. }
  8575. internal ArrayType/*!*/ GetArrayType(int rank, int numSizes, int numLoBounds, int[]/*!*/ sizes, int[]/*!*/ loBounds) {
  8576. if (this.arrayTypes == null) this.arrayTypes = new TrivialHashtable();
  8577. StringBuilder sb = new StringBuilder(rank*5);
  8578. for (int i = 0; i < rank; i++){
  8579. if (i < numLoBounds) sb.Append(loBounds[i]); else sb.Append('0');
  8580. if (i < numSizes){sb.Append(':'); sb.Append(sizes[i]);}
  8581. sb.Append(',');
  8582. }
  8583. Identifier id = Identifier.For(sb.ToString());
  8584. ArrayType result = (ArrayType)this.arrayTypes[id.UniqueIdKey];
  8585. if (result != null) return result;
  8586. lock(this){
  8587. result = (ArrayType)this.arrayTypes[id.UniqueIdKey];
  8588. if (result != null) return result;
  8589. if (loBounds == null) loBounds = new int[0];
  8590. this.arrayTypes[id.UniqueIdKey] = result = new ArrayType(this, rank, sizes, loBounds);
  8591. result.Flags &= ~TypeFlags.VisibilityMask;
  8592. result.Flags |= this.Flags & TypeFlags.VisibilityMask;
  8593. return result;
  8594. }
  8595. }
  8596. protected internal MemberList constructors;
  8597. public virtual MemberList GetConstructors(){
  8598. if (this.Members.Count != this.memberCount) this.constructors = null;
  8599. if (this.constructors != null) return this.constructors;
  8600. lock(this){
  8601. if (this.constructors != null) return this.constructors;
  8602. return this.constructors = TypeNode.WeedOutNonSpecialMethods(this.GetMembersNamed(StandardIds.Ctor), MethodFlags.RTSpecialName);
  8603. }
  8604. }
  8605. /// <summary>
  8606. /// Returns the constructor with the specified parameter types. Returns null if this type has no such constructor.
  8607. /// </summary>
  8608. public virtual InstanceInitializer GetConstructor(params TypeNode[] types){
  8609. return (InstanceInitializer)GetFirstMethod(this.GetConstructors(), types);
  8610. }
  8611. #if !NoXml
  8612. protected override Identifier GetDocumentationId(){
  8613. if (this.DeclaringType == null)
  8614. return Identifier.For("T:"+this.FullName);
  8615. else
  8616. return Identifier.For(this.DeclaringType.DocumentationId+"."+this.Name);
  8617. }
  8618. internal virtual void AppendDocumentIdMangledName(StringBuilder/*!*/ sb, TypeNodeList methodTypeParameters, TypeNodeList typeParameters) {
  8619. if (this.DeclaringType != null) {
  8620. this.DeclaringType.AppendDocumentIdMangledName(sb, methodTypeParameters, typeParameters);
  8621. sb.Append('.');
  8622. sb.Append(this.GetUnmangledNameWithoutTypeParameters());
  8623. }else
  8624. sb.Append(this.GetFullUnmangledNameWithoutTypeParameters());
  8625. TypeNodeList templateArguments = this.TemplateArguments;
  8626. int n = templateArguments == null ? 0 : templateArguments.Count;
  8627. if (n == 0) return;
  8628. sb.Append('{');
  8629. for (int i = 0; i < n; i++){
  8630. //^ assert templateArguments != null;
  8631. TypeNode templArg = templateArguments[i];
  8632. if (templArg == null) continue;
  8633. templArg.AppendDocumentIdMangledName(sb, methodTypeParameters, typeParameters);
  8634. if (i < n-1) sb.Append(',');
  8635. }
  8636. sb.Append('}');
  8637. }
  8638. #endif
  8639. internal TrivialHashtable modifierTable;
  8640. internal TypeNode/*!*/ GetModified(TypeNode/*!*/ modifierType, bool optionalModifier) {
  8641. if (this.modifierTable == null) this.modifierTable = new TrivialHashtable();
  8642. TypeNode result = (TypeNode)this.modifierTable[modifierType.UniqueKey];
  8643. if (result != null) return result;
  8644. result = optionalModifier ? (TypeNode)new OptionalModifier(modifierType, this) : (TypeNode)new RequiredModifier(modifierType, this);
  8645. this.modifierTable[modifierType.UniqueKey] = result;
  8646. return result;
  8647. }
  8648. public virtual TypeNode/*!*/ GetGenericTemplateInstance(Module/*!*/ module, TypeNodeList/*!*/ consolidatedArguments) {
  8649. if (this.DeclaringType == null)
  8650. return this.GetTemplateInstance(module, null, null, consolidatedArguments);
  8651. TypeNodeList myArgs = this.GetOwnTemplateArguments(consolidatedArguments);
  8652. if (myArgs == consolidatedArguments)
  8653. return this.GetTemplateInstance(module, null, this.DeclaringType, consolidatedArguments);
  8654. int n = consolidatedArguments.Count;
  8655. int m = myArgs == null ? 0 : myArgs.Count;
  8656. int k = n - m;
  8657. Debug.Assert(k > 0);
  8658. TypeNodeList parentArgs = new TypeNodeList(k);
  8659. for (int i = 0; i < k; i++) parentArgs.Add(consolidatedArguments[i]);
  8660. TypeNode declaringType = this.DeclaringType.GetGenericTemplateInstance(module, parentArgs);
  8661. TypeNode nestedType = declaringType.GetNestedType(this.Name);
  8662. if (nestedType == null) {
  8663. // can happen if a new nested type is added to a template
  8664. // see if the type appears in the original parent template
  8665. TypeNode declaringTypeTemplate = declaringType.Template;
  8666. TypeNode nestedTemplate = declaringTypeTemplate.GetNestedType(this.Name);
  8667. Duplicator duplicator = new Duplicator(module, null);
  8668. duplicator.RecordOriginalAsTemplate = true;
  8669. duplicator.SkipBodies = true;
  8670. duplicator.TypesToBeDuplicated[this.UniqueKey] = this;
  8671. nestedType = duplicator.VisitTypeNode(this, null, null, null, true);
  8672. Specializer specializer = new Specializer(module, declaringTypeTemplate.ConsolidatedTemplateParameters, declaringType.ConsolidatedTemplateArguments);
  8673. specializer.VisitTypeNode(nestedType);
  8674. nestedType.DeclaringType = declaringType;
  8675. declaringType.NestedTypes.Add(nestedType);
  8676. // Debug.Fail("template declaring type dummy instance does not have a nested type corresponding to template"); nestedType = this;
  8677. }
  8678. if (m == 0){Debug.Assert(nestedType.template != null); return nestedType;}
  8679. return nestedType.GetTemplateInstance(module, null, declaringType, myArgs);
  8680. }
  8681. public virtual TypeNode/*!*/ GetTemplateInstance(Module module, params TypeNode[] typeArguments) {
  8682. return this.GetTemplateInstance(module, null, null, new TypeNodeList(typeArguments));
  8683. }
  8684. protected virtual void TryToFindExistingInstance(Module/*!*/ module, TypeNode declaringType, TypeNodeList/*!*/ templateArguments, Identifier/*!*/ mangledName,
  8685. Identifier/*!*/ uniqueMangledName, out TypeNode result, out Identifier unusedMangledName){
  8686. unusedMangledName = null;
  8687. string mangledNameString = mangledName.Name;
  8688. int n = templateArguments.Count;
  8689. int tiCount = 0;
  8690. bool lookInReferencedAssemblies = TargetPlatform.GenericTypeNamesMangleChar != '`'; //REVIEW: huh? why not use IsGeneric?
  8691. result = module.GetStructurallyEquivalentType(this.Namespace == null ? Identifier.Empty : this.Namespace, mangledName, uniqueMangledName, lookInReferencedAssemblies);
  8692. if (this.IsGeneric){
  8693. if (result == null) unusedMangledName = mangledName;
  8694. return;
  8695. }
  8696. while (result != null){
  8697. //Mangled name is the same. But mangling is not unique (types are not qualified with assemblies), so check for equality.
  8698. if (this == result.Template && (declaringType == result.DeclaringType || !this.IsGeneric)){
  8699. bool goodMatch = (result.TemplateArguments != null || n == 0) && result.TemplateArguments.Count == n;
  8700. for (int i = 0; goodMatch && i < n; i++)
  8701. goodMatch = templateArguments[i] == result.TemplateArguments[i];
  8702. if (goodMatch) return;
  8703. }
  8704. //Mangle some more
  8705. mangledName = new Identifier(mangledNameString+(++tiCount).ToString());
  8706. result = module.GetStructurallyEquivalentType(this.Namespace == null ? Identifier.Empty : this.Namespace, mangledName, null, lookInReferencedAssemblies);
  8707. }
  8708. if (result == null) unusedMangledName = mangledName;
  8709. }
  8710. public virtual Identifier/*!*/ GetMangledTemplateInstanceName(TypeNodeList/*!*/ templateArguments, out Identifier/*!*/ uniqueMangledName, out bool notFullySpecialized){
  8711. StringBuilder mangledNameBuilder = new StringBuilder(this.Name.ToString());
  8712. StringBuilder uniqueMangledNameBuilder = new StringBuilder(this.Name.ToString());
  8713. uniqueMangledNameBuilder.Append(this.UniqueKey);
  8714. notFullySpecialized = false;
  8715. for (int i = 0, n = templateArguments.Count; i < n; i++){
  8716. if (i == 0){mangledNameBuilder.Append('<'); uniqueMangledNameBuilder.Append('<');}
  8717. TypeNode t = templateArguments[i];
  8718. if (t == null || t.Name == null) continue;
  8719. if (TypeIsNotFullySpecialized(t)) notFullySpecialized = true;
  8720. mangledNameBuilder.Append(t.FullName);
  8721. uniqueMangledNameBuilder.Append(t.FullName);
  8722. uniqueMangledNameBuilder.Append(t.UniqueKey);
  8723. if (i < n-1){
  8724. mangledNameBuilder.Append(',');
  8725. uniqueMangledNameBuilder.Append(',');
  8726. }else{
  8727. mangledNameBuilder.Append('>');
  8728. uniqueMangledNameBuilder.Append('>');
  8729. }
  8730. }
  8731. uniqueMangledName = Identifier.For(uniqueMangledNameBuilder.ToString());
  8732. return Identifier.For(mangledNameBuilder.ToString());
  8733. }
  8734. private static bool TypeIsNotFullySpecialized(TypeNode t) {
  8735. TypeNode tt = TypeNode.StripModifiers(t);
  8736. //^ assert tt != null;
  8737. if (tt is TypeParameter || tt is ClassParameter || tt.IsNotFullySpecialized)
  8738. return true;
  8739. for (int j = 0, m = tt.StructuralElementTypes == null ? 0 : tt.StructuralElementTypes.Count; j < m; j++) {
  8740. TypeNode et = tt.StructuralElementTypes[j];
  8741. if (et == null) continue;
  8742. if (TypeIsNotFullySpecialized(et)) return true;
  8743. }
  8744. return false;
  8745. }
  8746. /// <summary>
  8747. /// Gets an instance for the given template arguments of this (generic) template type.
  8748. /// </summary>
  8749. /// <param name="referringType">The type in which the reference to the template instance occurs. If the template is not
  8750. /// generic, the instance becomes a nested type of the referring type so that it has the same access privileges as the
  8751. /// code referrring to the instance.</param>
  8752. /// <param name="templateArguments">The template arguments.</param>
  8753. /// <returns>An instance of the template. Always the same instance for the same arguments.</returns>
  8754. public virtual TypeNode/*!*/ GetTemplateInstance(TypeNode referringType, params TypeNode[] templateArguments) {
  8755. return this.GetTemplateInstance(referringType, new TypeNodeList(templateArguments));
  8756. }
  8757. /// <summary>
  8758. /// Gets an instance for the given template arguments of this (generic) template type.
  8759. /// </summary>
  8760. /// <param name="referringType">The type in which the reference to the template instance occurs. If the template is not
  8761. /// generic, the instance becomes a nested type of the referring type so that it has the same access privileges as the
  8762. /// code referrring to the instance.</param>
  8763. /// <param name="templateArguments">The template arguments.</param>
  8764. /// <returns>An instance of the template. Always the same instance for the same arguments.</returns>
  8765. public virtual TypeNode/*!*/ GetTemplateInstance(TypeNode referringType, TypeNodeList templateArguments) {
  8766. if (referringType == null) return this;
  8767. Module module = referringType.DeclaringModule;
  8768. return this.GetTemplateInstance(module, referringType, this.DeclaringType, templateArguments);
  8769. }
  8770. class CachingModuleForGenericsInstances : Module{
  8771. public override TypeNode GetStructurallyEquivalentType(Identifier ns, Identifier/*!*/ id, Identifier uniqueMangledName, bool lookInReferencedAssemblies) {
  8772. if (uniqueMangledName == null) return null;
  8773. return (TypeNode)this.StructurallyEquivalentType[uniqueMangledName.UniqueIdKey];
  8774. }
  8775. }
  8776. protected static Module/*!*/ cachingModuleForGenericInstances = new CachingModuleForGenericsInstances();
  8777. public virtual TypeNode/*!*/ GetTemplateInstance(Module module, TypeNode referringType, TypeNode declaringType, TypeNodeList templateArguments) {
  8778. TypeNodeList templateParameters = this.TemplateParameters;
  8779. if (module == null || templateArguments == null || (declaringType == null && (templateParameters == null || templateParameters.Count == 0)))
  8780. return this;
  8781. if (this.IsGeneric){
  8782. referringType = null;
  8783. module = TypeNode.cachingModuleForGenericInstances;
  8784. }
  8785. bool notFullySpecialized;
  8786. Identifier/*!*/ uniqueMangledName;
  8787. Identifier mangledName = this.GetMangledTemplateInstanceName(templateArguments, out uniqueMangledName, out notFullySpecialized);
  8788. TypeNode result;
  8789. Identifier dummyId;
  8790. this.TryToFindExistingInstance(module, declaringType, templateArguments, mangledName, uniqueMangledName, out result, out dummyId);
  8791. if (result != null) return result;
  8792. if (this.NewTemplateInstanceIsRecursive) return this; //An instance of this template is trying to instantiate the template again
  8793. lock (Module.GlobalLock){
  8794. Identifier unusedMangledName;
  8795. this.TryToFindExistingInstance(module, declaringType, templateArguments, mangledName, uniqueMangledName, out result, out unusedMangledName);
  8796. if (result != null) return result;
  8797. //^ assume unusedMangledName != null;
  8798. TypeNodeList consolidatedTemplateArguments =
  8799. declaringType == null ? templateArguments : declaringType.GetConsolidatedTemplateArguments(templateArguments);
  8800. Duplicator duplicator = new Duplicator(module, referringType);
  8801. duplicator.RecordOriginalAsTemplate = true;
  8802. duplicator.SkipBodies = true;
  8803. duplicator.TypesToBeDuplicated[this.UniqueKey] = this;
  8804. result = duplicator.VisitTypeNode(this, unusedMangledName, consolidatedTemplateArguments, this.Template == null ? this : this.Template, true);
  8805. //^ assume result != null;
  8806. if (module == this.DeclaringModule){
  8807. if (this.TemplateInstances == null) this.TemplateInstances = new TypeNodeList();
  8808. this.TemplateInstances.Add(result);
  8809. }
  8810. result.Name = unusedMangledName;
  8811. result.Name.SourceContext = this.Name.SourceContext;
  8812. result.fullName = null;
  8813. if (this.IsGeneric) result.DeclaringModule = this.DeclaringModule;
  8814. result.DeclaringType = this.IsGeneric || referringType == null ? declaringType : referringType;
  8815. result.Template = this;
  8816. result.templateParameters = new TypeNodeList(0);
  8817. result.consolidatedTemplateParameters = new TypeNodeList(0);
  8818. result.templateArguments = templateArguments;
  8819. result.consolidatedTemplateArguments = consolidatedTemplateArguments;
  8820. result.IsNotFullySpecialized = notFullySpecialized || (declaringType != null && TypeIsNotFullySpecialized(declaringType));
  8821. module.StructurallyEquivalentType[unusedMangledName.UniqueIdKey] = result;
  8822. module.StructurallyEquivalentType[uniqueMangledName.UniqueIdKey] = result;
  8823. Specializer specializer = new Specializer(module, this.ConsolidatedTemplateParameters, consolidatedTemplateArguments);
  8824. specializer.VisitTypeNode(result);
  8825. TypeFlags visibility = this.Flags & TypeFlags.VisibilityMask;
  8826. for (int i = 0, m = templateArguments.Count; i < m; i++){
  8827. TypeNode t = templateArguments[i];
  8828. if (t == null) continue;
  8829. if (TypeIsNotFullySpecialized(t)) continue;
  8830. visibility = TypeNode.GetVisibilityIntersection(visibility, t.Flags & TypeFlags.VisibilityMask);
  8831. }
  8832. result.Flags &= ~TypeFlags.VisibilityMask;
  8833. result.Flags |= visibility;
  8834. if (this.IsGeneric) return result;
  8835. #if ExtendedRuntime
  8836. //Arrange for template instance to be emitted to module and to be recognized as a template instance when imported from module.
  8837. if (referringType == null){
  8838. if (visibility == TypeFlags.NestedPublic)
  8839. visibility = TypeFlags.Public;
  8840. else if (visibility != TypeFlags.Public)
  8841. visibility = TypeFlags.NotPublic;
  8842. module.Types.Add(result);
  8843. }else{
  8844. switch (visibility){
  8845. case TypeFlags.NestedFamANDAssem:
  8846. case TypeFlags.NestedFamily:
  8847. case TypeFlags.NestedPrivate:
  8848. if (result != referringType && this != referringType)
  8849. referringType.Members.Add(result);
  8850. else{
  8851. if (declaringType == null)
  8852. visibility = TypeFlags.NotPublic;
  8853. goto default;
  8854. }
  8855. break;
  8856. case TypeFlags.NestedAssembly:
  8857. if (declaringType == null)
  8858. visibility = TypeFlags.NotPublic;
  8859. goto default;
  8860. case TypeFlags.NestedPublic:
  8861. if (declaringType == null)
  8862. visibility = TypeFlags.Public;
  8863. goto default;
  8864. default:
  8865. if (declaringType == null){
  8866. result.DeclaringType = null;
  8867. module.Types.Add(result);
  8868. }else{
  8869. result.DeclaringType = declaringType;
  8870. declaringType.Members.Add(result);
  8871. }
  8872. break;
  8873. }
  8874. }
  8875. result.Flags &= ~TypeFlags.VisibilityMask;
  8876. result.Flags |= visibility;
  8877. AttributeList attrs = result.Attributes;
  8878. if (attrs == null) attrs = result.Attributes = new AttributeList(1);
  8879. TypeNode typeArray = CoreSystemTypes.Type.GetArrayType(1);
  8880. if (TypeNode.templateInstanceAttribute == null) {
  8881. InstanceInitializer constr = SystemTypes.TemplateInstanceAttribute.GetConstructor(CoreSystemTypes.Type, typeArray);
  8882. if (constr == null) { Debug.Fail(""); return result; }
  8883. TypeNode.templateInstanceAttribute = new MemberBinding(null, constr);
  8884. }
  8885. int n = templateArguments.Count;
  8886. TypeNode[] tArgs = new TypeNode[n];
  8887. for (int i = 0; i < n; i++) tArgs[i] = templateArguments[i];
  8888. AttributeNode attr = new AttributeNode(TypeNode.templateInstanceAttribute,
  8889. new ExpressionList(new Literal(this, CoreSystemTypes.Type), new Literal(tArgs, typeArray)));
  8890. attr.Target = AttributeTargets.Delegate|AttributeTargets.Class|AttributeTargets.Enum|AttributeTargets.Interface|AttributeTargets.Struct;
  8891. if (attrs.Count > 0 && attrs[0] == null)
  8892. attrs[0] = attr;
  8893. else
  8894. attrs.Add(attr);
  8895. #endif
  8896. return result;
  8897. }
  8898. }
  8899. protected virtual TypeNodeList GetConsolidatedTemplateArguments(){
  8900. TypeNodeList typeArgs = this.TemplateArguments;
  8901. if (this.DeclaringType == null) return typeArgs;
  8902. TypeNodeList result = this.DeclaringType.ConsolidatedTemplateArguments;
  8903. if (result == null){
  8904. if (this.DeclaringType.IsGeneric && this.DeclaringType.Template == null)
  8905. result = this.DeclaringType.ConsolidatedTemplateParameters;
  8906. if (result == null)
  8907. return typeArgs;
  8908. }
  8909. int n = typeArgs == null ? 0 : typeArgs.Count;
  8910. if (n == 0) return result;
  8911. result = result.Clone();
  8912. for (int i = 0; i < n; i++) result.Add(typeArgs[i]);
  8913. return result;
  8914. }
  8915. protected virtual TypeNodeList GetConsolidatedTemplateArguments(TypeNodeList typeArgs){
  8916. TypeNodeList result = this.ConsolidatedTemplateArguments;
  8917. if (result == null || result.Count == 0){
  8918. if (this.IsGeneric && this.Template == null)
  8919. result = this.ConsolidatedTemplateParameters;
  8920. else
  8921. return typeArgs;
  8922. }
  8923. int n = typeArgs == null ? 0 : typeArgs.Count;
  8924. if (n == 0) return result;
  8925. //^ assert typeArgs != null;
  8926. result = result.Clone();
  8927. for (int i = 0; i < n; i++) result.Add(typeArgs[i]);
  8928. return result;
  8929. }
  8930. protected virtual TypeNodeList GetConsolidatedTemplateParameters(){
  8931. TypeNodeList typeParams = this.TemplateParameters;
  8932. TypeNode declaringType = this.DeclaringType;
  8933. if (declaringType == null) return typeParams;
  8934. while (declaringType.Template != null) declaringType = declaringType.Template;
  8935. TypeNodeList result = declaringType.ConsolidatedTemplateParameters;
  8936. if (result == null) return typeParams;
  8937. int n = typeParams == null ? 0 : typeParams.Count;
  8938. if (n == 0) return result;
  8939. result = result.Clone();
  8940. for (int i = 0; i < n; i++) result.Add(typeParams[i]);
  8941. return result;
  8942. }
  8943. protected virtual TypeNodeList GetOwnTemplateArguments(TypeNodeList consolidatedTemplateArguments){
  8944. int n = this.TemplateParameters == null ? 0 : this.TemplateParameters.Count;
  8945. int m = consolidatedTemplateArguments == null ? 0 : consolidatedTemplateArguments.Count;
  8946. int k = m-n;
  8947. if (k <= 0) return consolidatedTemplateArguments;
  8948. TypeNodeList result = new TypeNodeList(n);
  8949. if (consolidatedTemplateArguments != null)
  8950. for (int i = 0; i < n; i++)
  8951. result.Add(consolidatedTemplateArguments[i+k]);
  8952. return result;
  8953. }
  8954. #if ExtendedRuntime
  8955. private static MemberBinding templateInstanceAttribute = null;
  8956. #endif
  8957. protected internal Pointer pointerType;
  8958. public virtual Pointer/*!*/ GetPointerType() {
  8959. Pointer result = this.pointerType;
  8960. if (result == null){
  8961. lock(this){
  8962. if (this.pointerType != null) return this.pointerType;
  8963. result = this.pointerType = new Pointer(this);
  8964. result.Flags &= ~TypeFlags.VisibilityMask;
  8965. result.Flags |= this.Flags & TypeFlags.VisibilityMask;
  8966. result.DeclaringModule = this.DeclaringModule;
  8967. }
  8968. }
  8969. return result;
  8970. }
  8971. protected internal Reference referenceType;
  8972. public virtual Reference/*!*/ GetReferenceType(){
  8973. Reference result = this.referenceType;
  8974. if (result == null){
  8975. lock(this){
  8976. if (this.referenceType != null) return this.referenceType;
  8977. result = this.referenceType = new Reference(this);
  8978. result.Flags &= ~TypeFlags.VisibilityMask;
  8979. result.Flags |= this.Flags & TypeFlags.VisibilityMask;
  8980. result.DeclaringModule = this.DeclaringModule;
  8981. }
  8982. }
  8983. return result;
  8984. }
  8985. //^ [Microsoft.Contracts.SpecPublic]
  8986. protected internal TrivialHashtable memberTable;
  8987. protected internal int memberCount;
  8988. /// <summary>
  8989. /// Returns a list of all the members declared directly by this type with the specified name.
  8990. /// Returns an empty list if this type has no such members.
  8991. /// </summary>
  8992. public virtual MemberList/*!*/ GetMembersNamed(Identifier name) {
  8993. if (name == null) return new MemberList(0);
  8994. MemberList members = this.Members;
  8995. int n = members == null ? 0 : members.Count;
  8996. if (n != this.memberCount || this.memberTable == null) this.UpdateMemberTable(n);
  8997. //^ assert this.memberTable != null;
  8998. MemberList result = (MemberList)this.memberTable[name.UniqueIdKey];
  8999. if (result == null){
  9000. lock(this){
  9001. result = (MemberList)this.memberTable[name.UniqueIdKey];
  9002. if (result != null) return result;
  9003. this.memberTable[name.UniqueIdKey] = (result = new MemberList());
  9004. }
  9005. }
  9006. return result;
  9007. }
  9008. /// <summary>
  9009. /// Returns the first event declared by this type with the specified name.
  9010. /// Returns null if this type has no such event.
  9011. /// </summary>
  9012. public virtual Event GetEvent(Identifier name){
  9013. MemberList members = this.GetMembersNamed(name);
  9014. for (int i = 0, n = members.Count; i < n; i++){
  9015. Event ev = members[i] as Event;
  9016. if (ev != null) return ev;
  9017. }
  9018. return null;
  9019. }
  9020. /// <summary>
  9021. /// Returns the first field declared by this type with the specified name. Returns null if this type has no such field.
  9022. /// </summary>
  9023. public virtual Field GetField(Identifier name){
  9024. MemberList members = this.GetMembersNamed(name);
  9025. for (int i = 0, n = members.Count; i < n; i++){
  9026. Field field = members[i] as Field;
  9027. if (field != null) return field;
  9028. }
  9029. return null;
  9030. }
  9031. /// <summary>
  9032. /// Returns the first method declared by this type with the specified name and parameter types. Returns null if this type has no such method.
  9033. /// </summary>
  9034. /// <returns></returns>
  9035. public virtual Method GetMethod(Identifier name, params TypeNode[] types){
  9036. return GetFirstMethod(this.GetMembersNamed(name), types);
  9037. }
  9038. private static Method GetFirstMethod(MemberList members, params TypeNode[] types){
  9039. if (members == null) return null;
  9040. int m = types == null ? 0 : types.Length;
  9041. TypeNodeList typeNodes = m == 0 ? null : new TypeNodeList(types);
  9042. for (int i = 0, n = members.Count; i < n; i++){
  9043. Method meth = members[i] as Method;
  9044. if (meth == null) continue;
  9045. if (meth.ParameterTypesMatchStructurally(typeNodes)) return meth;
  9046. }
  9047. return null;
  9048. }
  9049. public virtual MethodList GetMethods(Identifier name, params TypeNode[] types) {
  9050. return GetMethods(this.GetMembersNamed(name), types);
  9051. }
  9052. private static MethodList GetMethods(MemberList members, params TypeNode[] types) {
  9053. if (members == null) return null;
  9054. int m = types == null ? 0 : types.Length;
  9055. MethodList result = new MethodList();
  9056. TypeNodeList typeNodes = m == 0 ? null : new TypeNodeList(types);
  9057. for (int i = 0, n = members.Count; i < n; i++) {
  9058. Method meth = members[i] as Method;
  9059. if (meth == null) continue;
  9060. if (meth.ParameterTypesMatchStructurally(typeNodes)) result.Add(meth);
  9061. }
  9062. return result;
  9063. }
  9064. public Method GetMatchingMethod(Method method) {
  9065. if (method == null || method.Name == null) return null;
  9066. MemberList members = this.GetMembersNamed(method.Name);
  9067. for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++){
  9068. Method m = members[i] as Method;
  9069. if (m == null) continue;
  9070. if (m.ParametersMatchStructurally(method.Parameters)) return m;
  9071. }
  9072. return null;
  9073. }
  9074. /// <summary>
  9075. /// Returns the first nested type declared by this type with the specified name. Returns null if this type has no such nested type.
  9076. /// </summary>
  9077. public virtual TypeNode GetNestedType(Identifier name){
  9078. if (name == null) return null;
  9079. if (this.members != null){
  9080. MemberList members = this.GetMembersNamed(name);
  9081. for (int i = 0, n = members.Count; i < n; i++){
  9082. TypeNode type = members[i] as TypeNode;
  9083. if (type != null) return type;
  9084. }
  9085. return null;
  9086. }
  9087. TypeNodeList nestedTypes = this.NestedTypes;
  9088. for (int i = 0, n = nestedTypes == null ? 0 : nestedTypes.Count; i < n; i++) {
  9089. TypeNode type = nestedTypes[i];
  9090. if (type != null && type.Name.UniqueIdKey == name.UniqueIdKey) return type;
  9091. }
  9092. return null;
  9093. }
  9094. protected internal TypeNodeList nestedTypes;
  9095. public virtual TypeNodeList NestedTypes{
  9096. get{
  9097. if (this.nestedTypes != null && (this.members == null || this.members.Count == this.memberCount))
  9098. return this.nestedTypes;
  9099. if (this.ProvideNestedTypes != null && this.ProviderHandle != null){
  9100. lock (Module.GlobalLock){
  9101. this.ProvideNestedTypes(this, this.ProviderHandle);
  9102. }
  9103. }else{
  9104. MemberList members = this.Members;
  9105. TypeNodeList nestedTypes = new TypeNodeList();
  9106. for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++){
  9107. TypeNode nt = members[i] as TypeNode;
  9108. if (nt == null) continue;
  9109. nestedTypes.Add(nt);
  9110. }
  9111. this.nestedTypes = nestedTypes;
  9112. }
  9113. return this.nestedTypes;
  9114. }
  9115. set{
  9116. this.nestedTypes = value;
  9117. }
  9118. }
  9119. /// <summary>
  9120. /// Returns the first property declared by this type with the specified name and parameter types. Returns null if this type has no such property.
  9121. /// </summary>
  9122. public virtual Property GetProperty(Identifier name, params TypeNode[] types){
  9123. return GetProperty(this.GetMembersNamed(name), types);
  9124. }
  9125. private static Property GetProperty(MemberList members, params TypeNode[] types){
  9126. if (members == null) return null;
  9127. int m = types == null ? 0 : types.Length;
  9128. TypeNodeList typeNodes = m == 0 ? null : new TypeNodeList(types);
  9129. for (int i = 0, n = members.Count; i < n; i++){
  9130. Property prop = members[i] as Property;
  9131. if (prop == null) continue;
  9132. if (prop.ParameterTypesMatch(typeNodes)) return prop;
  9133. }
  9134. return null;
  9135. }
  9136. #if !MinimalReader
  9137. protected internal MemberList explicitCoercionMethods;
  9138. public virtual MemberList ExplicitCoercionMethods{
  9139. get{
  9140. if (this.Members.Count != this.memberCount) this.explicitCoercionMethods = null;
  9141. if (this.explicitCoercionMethods != null) return this.explicitCoercionMethods;
  9142. lock(this){
  9143. if (this.explicitCoercionMethods != null) return this.explicitCoercionMethods;
  9144. return this.explicitCoercionMethods = TypeNode.WeedOutNonSpecialMethods(this.GetMembersNamed(StandardIds.opExplicit), MethodFlags.SpecialName);
  9145. }
  9146. }
  9147. }
  9148. protected internal MemberList implicitCoercionMethods;
  9149. public virtual MemberList ImplicitCoercionMethods{
  9150. get{
  9151. if (this.Members.Count != this.memberCount) this.implicitCoercionMethods = null;
  9152. if (this.implicitCoercionMethods != null) return this.implicitCoercionMethods;
  9153. lock(this){
  9154. if (this.implicitCoercionMethods != null) return this.implicitCoercionMethods;
  9155. return this.implicitCoercionMethods = TypeNode.WeedOutNonSpecialMethods(this.GetMembersNamed(StandardIds.opImplicit), MethodFlags.SpecialName);
  9156. }
  9157. }
  9158. }
  9159. protected readonly static Method MethodDoesNotExist = new Method();
  9160. protected internal TrivialHashtable explicitCoercionFromTable;
  9161. public virtual Method GetExplicitCoercionFromMethod(TypeNode sourceType){
  9162. if (sourceType == null) return null;
  9163. Method result = null;
  9164. if (this.explicitCoercionFromTable != null)
  9165. result = (Method)this.explicitCoercionFromTable[sourceType.UniqueKey];
  9166. if (result == TypeNode.MethodDoesNotExist) return null;
  9167. if (result != null) return result;
  9168. lock(this){
  9169. if (this.explicitCoercionFromTable != null)
  9170. result = (Method)this.explicitCoercionFromTable[sourceType.UniqueKey];
  9171. if (result == TypeNode.MethodDoesNotExist) return null;
  9172. if (result != null) return result;
  9173. MemberList coercions = this.ExplicitCoercionMethods;
  9174. for (int i = 0, n = coercions.Count; i < n; i++){
  9175. Method m = (Method)coercions[i];
  9176. if (sourceType == m.Parameters[0].Type){result = m; break;}
  9177. }
  9178. if (this.explicitCoercionFromTable == null)
  9179. this.explicitCoercionFromTable = new TrivialHashtable();
  9180. if (result == null)
  9181. this.explicitCoercionFromTable[sourceType.UniqueKey] = TypeNode.MethodDoesNotExist;
  9182. else
  9183. this.explicitCoercionFromTable[sourceType.UniqueKey] = result;
  9184. return result;
  9185. }
  9186. }
  9187. protected internal TrivialHashtable explicitCoercionToTable;
  9188. public virtual Method GetExplicitCoercionToMethod(TypeNode targetType){
  9189. if (targetType == null) return null;
  9190. Method result = null;
  9191. if (this.explicitCoercionToTable != null)
  9192. result = (Method)this.explicitCoercionToTable[targetType.UniqueKey];
  9193. if (result == TypeNode.MethodDoesNotExist) return null;
  9194. if (result != null) return result;
  9195. lock(this){
  9196. if (this.explicitCoercionToTable != null)
  9197. result = (Method)this.explicitCoercionToTable[targetType.UniqueKey];
  9198. if (result == TypeNode.MethodDoesNotExist) return null;
  9199. if (result != null) return result;
  9200. MemberList coercions = this.ExplicitCoercionMethods;
  9201. for (int i = 0, n = coercions.Count; i < n; i++){
  9202. Method m = (Method)coercions[i];
  9203. if (m.ReturnType == targetType){result = m; break;}
  9204. }
  9205. if (this.explicitCoercionToTable == null)
  9206. this.explicitCoercionToTable = new TrivialHashtable();
  9207. if (result == null)
  9208. this.explicitCoercionToTable[targetType.UniqueKey] = TypeNode.MethodDoesNotExist;
  9209. else
  9210. this.explicitCoercionToTable[targetType.UniqueKey] = result;
  9211. }
  9212. return result;
  9213. }
  9214. protected internal TrivialHashtable implicitCoercionFromTable;
  9215. public virtual Method GetImplicitCoercionFromMethod(TypeNode sourceType){
  9216. if (sourceType == null) return null;
  9217. Method result = null;
  9218. if (this.implicitCoercionFromTable != null)
  9219. result = (Method)this.implicitCoercionFromTable[sourceType.UniqueKey];
  9220. if (result == TypeNode.MethodDoesNotExist) return null;
  9221. if (result != null) return result;
  9222. lock(this){
  9223. if (this.implicitCoercionFromTable != null)
  9224. result = (Method)this.implicitCoercionFromTable[sourceType.UniqueKey];
  9225. if (result == TypeNode.MethodDoesNotExist) return null;
  9226. if (result != null) return result;
  9227. MemberList coercions = this.ImplicitCoercionMethods;
  9228. for (int i = 0, n = coercions.Count; i < n; i++){
  9229. Method m = (Method)coercions[i];
  9230. if (sourceType.IsStructurallyEquivalentTo(TypeNode.StripModifiers(m.Parameters[0].Type))){result = m; break;}
  9231. }
  9232. if (this.implicitCoercionFromTable == null)
  9233. this.implicitCoercionFromTable = new TrivialHashtable();
  9234. if (result == null)
  9235. this.implicitCoercionFromTable[sourceType.UniqueKey] = TypeNode.MethodDoesNotExist;
  9236. else
  9237. this.implicitCoercionFromTable[sourceType.UniqueKey] = result;
  9238. return result;
  9239. }
  9240. }
  9241. protected internal TrivialHashtable implicitCoercionToTable;
  9242. public virtual Method GetImplicitCoercionToMethod(TypeNode targetType){
  9243. if (targetType == null) return null;
  9244. Method result = null;
  9245. if (this.implicitCoercionToTable != null)
  9246. result = (Method)this.implicitCoercionToTable[targetType.UniqueKey];
  9247. if (result == TypeNode.MethodDoesNotExist) return null;
  9248. if (result != null) return result;
  9249. lock(this){
  9250. if (this.implicitCoercionToTable != null)
  9251. result = (Method)this.implicitCoercionToTable[targetType.UniqueKey];
  9252. if (result == TypeNode.MethodDoesNotExist) return null;
  9253. if (result != null) return result;
  9254. MemberList coercions = this.ImplicitCoercionMethods;
  9255. for (int i = 0, n = coercions.Count; i < n; i++){
  9256. Method m = (Method)coercions[i];
  9257. if (m.ReturnType == targetType){result = m; break;}
  9258. }
  9259. if (this.implicitCoercionToTable == null)
  9260. this.implicitCoercionToTable = new TrivialHashtable();
  9261. if (result == null)
  9262. this.implicitCoercionToTable[targetType.UniqueKey] = TypeNode.MethodDoesNotExist;
  9263. else
  9264. this.implicitCoercionToTable[targetType.UniqueKey] = result;
  9265. return result;
  9266. }
  9267. }
  9268. protected Method opFalse;
  9269. public virtual Method GetOpFalse(){
  9270. Method result = this.opFalse;
  9271. if (result == TypeNode.MethodDoesNotExist) return null;
  9272. if (result != null) return result;
  9273. MemberList members = this.Members; //evaluate for side effect
  9274. if (members != null) members = null;
  9275. lock(this){
  9276. result = this.opFalse;
  9277. if (result == TypeNode.MethodDoesNotExist) return null;
  9278. if (result != null) return result;
  9279. TypeNode t = this;
  9280. while (t != null){
  9281. MemberList opFalses = t.GetMembersNamed(StandardIds.opFalse);
  9282. if (opFalses != null)
  9283. for (int i = 0, n = opFalses.Count; i < n; i++){
  9284. Method opFalse = opFalses[i] as Method;
  9285. if (opFalse == null) continue;
  9286. if (!opFalse.IsSpecialName || !opFalse.IsStatic || !opFalse.IsPublic || opFalse.ReturnType != CoreSystemTypes.Boolean ||
  9287. opFalse.Parameters == null || opFalse.Parameters.Count != 1) continue;
  9288. return this.opFalse = opFalse;
  9289. }
  9290. t = t.BaseType;
  9291. }
  9292. this.opFalse = TypeNode.MethodDoesNotExist;
  9293. return null;
  9294. }
  9295. }
  9296. protected Method opTrue;
  9297. public virtual Method GetOpTrue(){
  9298. Method result = this.opTrue;
  9299. if (result == TypeNode.MethodDoesNotExist) return null;
  9300. if (result != null) return result;
  9301. MemberList members = this.Members; //evaluate for side effect
  9302. if (members != null) members = null;
  9303. lock(this){
  9304. result = this.opTrue;
  9305. if (result == TypeNode.MethodDoesNotExist) return null;
  9306. if (result != null) return result;
  9307. TypeNode t = this;
  9308. while (t != null){
  9309. MemberList opTrues = t.GetMembersNamed(StandardIds.opTrue);
  9310. if (opTrues != null)
  9311. for (int i = 0, n = opTrues.Count; i < n; i++){
  9312. Method opTrue = opTrues[i] as Method;
  9313. if (opTrue == null) continue;
  9314. if (!opTrue.IsSpecialName || !opTrue.IsStatic || !opTrue.IsPublic || opTrue.ReturnType != CoreSystemTypes.Boolean ||
  9315. opTrue.Parameters == null || opTrue.Parameters.Count != 1) continue;
  9316. return this.opTrue = opTrue;
  9317. }
  9318. t = t.BaseType;
  9319. }
  9320. this.opTrue = TypeNode.MethodDoesNotExist;
  9321. return null;
  9322. }
  9323. }
  9324. #endif
  9325. #if !NoReflection
  9326. private static Hashtable typeMap; //contains weak references
  9327. /// <summary>
  9328. /// Gets a TypeNode instance corresponding to the given System.Type instance.
  9329. /// </summary>
  9330. /// <param name="type">A runtime type.</param>
  9331. /// <returns>A TypeNode instance.</returns>
  9332. public static TypeNode GetTypeNode(System.Type type){
  9333. if (type == null) return null;
  9334. Hashtable typeMap = TypeNode.typeMap;
  9335. if (typeMap == null) TypeNode.typeMap = typeMap = Hashtable.Synchronized(new Hashtable());
  9336. TypeNode result = null;
  9337. WeakReference wr = (WeakReference)typeMap[type];
  9338. if (wr != null){
  9339. result = wr.Target as TypeNode;
  9340. if (result == Class.DoesNotExist) return null;
  9341. if (result != null) return result;
  9342. }
  9343. #if WHIDBEY
  9344. if (type.IsGenericType && !type.IsGenericTypeDefinition){
  9345. try{
  9346. TypeNode template = TypeNode.GetTypeNode(type.GetGenericTypeDefinition());
  9347. if (template == null) return null;
  9348. TypeNodeList templateArguments = new TypeNodeList();
  9349. foreach (Type arg in type.GetGenericArguments())
  9350. templateArguments.Add(TypeNode.GetTypeNode(arg));
  9351. return template.GetGenericTemplateInstance(template.DeclaringModule, templateArguments);
  9352. }catch{
  9353. //TODO: log error
  9354. return null;
  9355. }
  9356. }
  9357. if (type.IsGenericParameter){
  9358. try{
  9359. int parIndx = type.GenericParameterPosition;
  9360. System.Reflection.MethodInfo mi = type.DeclaringMethod as System.Reflection.MethodInfo;
  9361. if (mi != null){
  9362. Method m = Method.GetMethod(mi);
  9363. if (m == null) return null;
  9364. if (m.TemplateParameters != null && m.TemplateParameters.Count > parIndx)
  9365. return m.TemplateParameters[parIndx];
  9366. }else{
  9367. System.Type ti = type.DeclaringType;
  9368. TypeNode t = TypeNode.GetTypeNode(ti);
  9369. if (t == null) return null;
  9370. if (t.TemplateParameters != null && t.TemplateParameters.Count > parIndx)
  9371. return t.TemplateParameters[parIndx];
  9372. }
  9373. return null;
  9374. }catch{
  9375. //TODO: log error
  9376. return null;
  9377. }
  9378. }
  9379. #endif
  9380. if (type.HasElementType){
  9381. TypeNode elemType = TypeNode.GetTypeNode(type.GetElementType());
  9382. if (elemType == null) return null;
  9383. if (type.IsArray)
  9384. result = elemType.GetArrayType(type.GetArrayRank());
  9385. else if (type.IsByRef)
  9386. result = elemType.GetReferenceType();
  9387. else if (type.IsPointer)
  9388. result = elemType.GetPointerType();
  9389. else{
  9390. Debug.Assert(false);
  9391. result = null;
  9392. }
  9393. }else if (type.DeclaringType != null){
  9394. TypeNode dType = TypeNode.GetTypeNode(type.DeclaringType);
  9395. if (dType == null) return null;
  9396. result = dType.GetNestedType(Identifier.For(type.Name));
  9397. }else{
  9398. AssemblyNode assem = AssemblyNode.GetAssembly(type.Assembly);
  9399. if (assem != null){
  9400. result = assem.GetType(Identifier.For(type.Namespace), Identifier.For(type.Name));
  9401. }
  9402. }
  9403. if (result == null)
  9404. typeMap[type] = new WeakReference(Class.DoesNotExist);
  9405. else
  9406. typeMap[type] = new WeakReference(result);
  9407. return result;
  9408. }
  9409. protected internal Type runtimeType;
  9410. /// <summary>
  9411. /// Gets a System.Type instance corresponding to this type. The assembly containin this type must be normalized
  9412. /// and must have a location on disk or must have been loaded via AssemblyNode.GetRuntimeAssembly.
  9413. /// </summary>
  9414. /// <returns>A System.Type instance. (A runtime type.)</returns>
  9415. public virtual Type GetRuntimeType(){
  9416. if (this.runtimeType == null){
  9417. lock(this){
  9418. if (this.runtimeType != null) return this.runtimeType;
  9419. #if WHIDBEY
  9420. if (this.IsGeneric && this.Template != null){
  9421. try {
  9422. TypeNode rootTemplate = this.Template;
  9423. while (rootTemplate.Template != null)
  9424. rootTemplate = rootTemplate.Template;
  9425. Type genType = rootTemplate.GetRuntimeType();
  9426. if (genType == null) return null;
  9427. TypeNodeList args = this.ConsolidatedTemplateArguments;
  9428. Type[] arguments = new Type[args.Count];
  9429. for (int i = 0; i < args.Count; i++) arguments[i] = args[i].GetRuntimeType();
  9430. return genType.MakeGenericType(arguments);
  9431. }catch{
  9432. //TODO: add error to metadata import errors if type is imported
  9433. return null;
  9434. }
  9435. }
  9436. #endif
  9437. if (this.DeclaringType != null){
  9438. Type dt = this.DeclaringType.GetRuntimeType();
  9439. if (dt != null){
  9440. System.Reflection.BindingFlags flags = System.Reflection.BindingFlags.DeclaredOnly;
  9441. if (this.IsPublic) flags |= System.Reflection.BindingFlags.Public; else flags |= System.Reflection.BindingFlags.NonPublic;
  9442. this.runtimeType = dt.GetNestedType(this.Name.ToString(), flags);
  9443. }
  9444. }else if (this.DeclaringModule != null && this.DeclaringModule.IsNormalized && this.DeclaringModule.ContainingAssembly != null){
  9445. System.Reflection.Assembly runtimeAssembly = this.DeclaringModule.ContainingAssembly.GetRuntimeAssembly();
  9446. if (runtimeAssembly != null)
  9447. this.runtimeType = runtimeAssembly.GetType(this.FullName, false);
  9448. }
  9449. }
  9450. }
  9451. return this.runtimeType;
  9452. }
  9453. #endif
  9454. public static TypeFlags GetVisibilityIntersection(TypeFlags vis1, TypeFlags vis2){
  9455. switch (vis2){
  9456. case TypeFlags.Public:
  9457. case TypeFlags.NestedPublic:
  9458. return vis1;
  9459. case TypeFlags.NotPublic:
  9460. case TypeFlags.NestedAssembly:
  9461. switch (vis1){
  9462. case TypeFlags.Public:
  9463. return vis2;
  9464. case TypeFlags.NestedPublic:
  9465. case TypeFlags.NestedFamORAssem:
  9466. return TypeFlags.NestedAssembly;
  9467. case TypeFlags.NestedFamily:
  9468. return TypeFlags.NestedFamANDAssem;
  9469. default:
  9470. return vis1;
  9471. }
  9472. case TypeFlags.NestedFamANDAssem:
  9473. switch (vis1){
  9474. case TypeFlags.Public:
  9475. case TypeFlags.NestedPublic:
  9476. case TypeFlags.NestedFamORAssem:
  9477. case TypeFlags.NestedFamily:
  9478. return TypeFlags.NestedFamANDAssem;
  9479. default:
  9480. return vis1;
  9481. }
  9482. case TypeFlags.NestedFamORAssem:
  9483. switch (vis1){
  9484. case TypeFlags.Public:
  9485. case TypeFlags.NestedPublic:
  9486. return TypeFlags.NestedFamORAssem;
  9487. default:
  9488. return vis1;
  9489. }
  9490. case TypeFlags.NestedFamily:
  9491. switch (vis1){
  9492. case TypeFlags.Public:
  9493. case TypeFlags.NestedPublic:
  9494. case TypeFlags.NestedFamORAssem:
  9495. return TypeFlags.NestedFamily;
  9496. case TypeFlags.NestedAssembly:
  9497. return TypeFlags.NestedFamANDAssem;
  9498. default:
  9499. return vis1;
  9500. }
  9501. default:
  9502. return TypeFlags.NestedPrivate;
  9503. }
  9504. }
  9505. private TrivialHashtable explicitInterfaceImplementations;
  9506. public bool ImplementsExplicitly(Method method){
  9507. if (method == null) return false;
  9508. TrivialHashtable explicitInterfaceImplementations = this.explicitInterfaceImplementations;
  9509. if (explicitInterfaceImplementations == null){
  9510. MemberList members = this.Members;
  9511. lock(this){
  9512. if ((explicitInterfaceImplementations = this.explicitInterfaceImplementations) == null){
  9513. explicitInterfaceImplementations = this.explicitInterfaceImplementations = new TrivialHashtable();
  9514. for (int i = 0, n = members.Count; i < n; i++){
  9515. Method m = members[i] as Method;
  9516. if (m == null) continue;
  9517. MethodList implementedInterfaceMethods = m.ImplementedInterfaceMethods;
  9518. if (implementedInterfaceMethods != null)
  9519. for (int j = 0, k = implementedInterfaceMethods.Count; j < k; j++){
  9520. Method im = implementedInterfaceMethods[j];
  9521. if (im == null) continue;
  9522. explicitInterfaceImplementations[im.UniqueKey] = m;
  9523. }
  9524. }
  9525. }
  9526. }
  9527. }
  9528. return explicitInterfaceImplementations[method.UniqueKey] != null;
  9529. }
  9530. public Method ExplicitImplementation(Method method)
  9531. {
  9532. if (ImplementsExplicitly(method)) return (Method)explicitInterfaceImplementations[method.UniqueKey];
  9533. return null;
  9534. }
  9535. #if !MinimalReader
  9536. internal bool ImplementsMethod(Method meth, bool checkPublic){
  9537. return this.GetImplementingMethod(meth, checkPublic) != null;
  9538. }
  9539. public Method GetImplementingMethod(Method meth, bool checkPublic){
  9540. if (meth == null) return null;
  9541. MemberList mems = this.GetMembersNamed(meth.Name);
  9542. for (int j = 0, m = mems == null ? 0 : mems.Count; j < m; j++){
  9543. Method locM = mems[j] as Method;
  9544. if (locM == null || !locM.IsVirtual || (checkPublic && !locM.IsPublic)) continue;
  9545. if ((locM.ReturnType != meth.ReturnType && !(locM.ReturnType != null && locM.ReturnType.IsStructurallyEquivalentTo(meth.ReturnType))) ||
  9546. !locM.ParametersMatchStructurally(meth.Parameters)) continue;
  9547. return locM;
  9548. }
  9549. if (checkPublic && this.BaseType != null)
  9550. return this.BaseType.GetImplementingMethod(meth, true);
  9551. return null;
  9552. }
  9553. #endif
  9554. /// <summary>
  9555. /// Returns true if the CLR CTS allows a value of this type may be assigned to a variable of the target type (possibly after boxing),
  9556. /// either because the target type is the same or a base type, or because the target type is an interface implemented by this type or the implementor of this type,
  9557. /// or because this type and the target type are zero based single dimensional arrays with assignment compatible reference element types
  9558. /// </summary>
  9559. public virtual bool IsAssignableTo(TypeNode targetType){
  9560. if (this == CoreSystemTypes.Void) return false;
  9561. if (targetType == this) return true;
  9562. if (this == CoreSystemTypes.Object) return false;
  9563. if (targetType == CoreSystemTypes.Object || this.IsStructurallyEquivalentTo(targetType) ||
  9564. this.BaseType != null && (this.BaseType.IsAssignableTo(targetType)))
  9565. return true;
  9566. if (this.BaseType != null && this.ConsolidatedTemplateParameters != null && this.BaseType.Template != null && this.BaseType.Template.IsAssignableTo(targetType))
  9567. return true; //When seeing if one template is assignable to another, be sure to strip off template instances along the inheritance chain
  9568. InterfaceList interfaces = this.Interfaces;
  9569. if (interfaces == null) return false;
  9570. for (int i = 0, n = interfaces.Count; i < n; i++){
  9571. Interface iface = interfaces[i];
  9572. if (iface == null) continue;
  9573. if (iface.IsAssignableTo(targetType)) return true;
  9574. if (iface.Template != null && this.ConsolidatedTemplateParameters != null && iface.Template.IsAssignableTo(targetType))
  9575. return true; //When seeing if one template is assignable to another, be sure to strip off template instances along the inheritance chain
  9576. }
  9577. return false;
  9578. }
  9579. /// <summary>
  9580. /// Returns true if this type is assignable to some instance of the given template.
  9581. /// </summary>
  9582. public virtual bool IsAssignableToInstanceOf(TypeNode targetTemplate){
  9583. if (this == CoreSystemTypes.Void || targetTemplate == null) return false;
  9584. if (targetTemplate.IsStructurallyEquivalentTo(this.Template == null ? this : this.Template) ||
  9585. this.BaseType != null && (this.BaseType.IsAssignableToInstanceOf(targetTemplate) ||
  9586. this.BaseType.Template != null && this.BaseType.Template.IsAssignableToInstanceOf(targetTemplate))) return true;
  9587. InterfaceList interfaces = this.Interfaces;
  9588. if (interfaces == null) return false;
  9589. for (int i = 0, n = interfaces.Count; i < n; i++) {
  9590. Interface iface = interfaces[i];
  9591. if (iface == null) continue;
  9592. if (iface.IsAssignableToInstanceOf(targetTemplate)) return true;
  9593. }
  9594. return false;
  9595. }
  9596. /// <summary>
  9597. /// Returns true if this type is assignable to some instance of the given template.
  9598. /// </summary>
  9599. public virtual bool IsAssignableToInstanceOf(TypeNode targetTemplate, out TypeNodeList templateArguments){
  9600. templateArguments = null;
  9601. if (this == CoreSystemTypes.Void || targetTemplate == null) return false;
  9602. if (targetTemplate == this.Template){
  9603. templateArguments = this.TemplateArguments;
  9604. return true;
  9605. }
  9606. if (this != CoreSystemTypes.Object && this.BaseType != null && this.BaseType.IsAssignableToInstanceOf(targetTemplate, out templateArguments)) return true;
  9607. InterfaceList interfaces = this.Interfaces;
  9608. if (interfaces == null) return false;
  9609. for (int i = 0, n = interfaces.Count; i < n; i++) {
  9610. Interface iface = interfaces[i];
  9611. if (iface == null) continue;
  9612. if (iface.IsAssignableToInstanceOf(targetTemplate, out templateArguments)) return true;
  9613. }
  9614. return false;
  9615. }
  9616. /// <summary>
  9617. /// Returns true if otherType is the base class of this type or if the base class of this type is derived from otherType.
  9618. /// </summary>
  9619. public virtual bool IsDerivedFrom(TypeNode otherType){
  9620. if (otherType == null) return false;
  9621. TypeNode baseType = this.BaseType;
  9622. while (baseType != null){
  9623. if (baseType == otherType) return true;
  9624. baseType = baseType.BaseType;
  9625. }
  9626. return false;
  9627. }
  9628. #if !MinimalReader
  9629. // Not thread safe code...
  9630. bool isCheckingInheritedFrom = false;
  9631. public virtual bool IsInheritedFrom(TypeNode otherType) {
  9632. if (otherType == null) return false;
  9633. if (this == otherType) return true;
  9634. bool result = false;
  9635. if (this.isCheckingInheritedFrom)
  9636. goto done;
  9637. this.isCheckingInheritedFrom = true;
  9638. if (this.Template != null) {
  9639. result = this.Template.IsInheritedFrom(otherType);
  9640. goto done;
  9641. }
  9642. if (otherType.Template != null) {
  9643. otherType = otherType.Template;
  9644. }
  9645. TypeNode baseType = this.BaseType;
  9646. if (baseType != null && baseType.IsInheritedFrom(otherType)) {
  9647. result = true;
  9648. goto done;
  9649. }
  9650. InterfaceList interfaces = this.Interfaces;
  9651. if (interfaces == null) goto done;
  9652. for (int i = 0, n = interfaces.Count; i < n; i++) {
  9653. Interface iface = interfaces[i];
  9654. if (iface == null) continue;
  9655. if (iface.IsInheritedFrom(otherType)) {
  9656. result = true;
  9657. goto done;
  9658. }
  9659. }
  9660. done:
  9661. this.isCheckingInheritedFrom = false;
  9662. return result;
  9663. }
  9664. #endif
  9665. public virtual bool IsStructurallyEquivalentTo(TypeNode type){
  9666. if (null == (object)type) return false;
  9667. if (this == type) return true;
  9668. if (this.Template == (object)null || type.Template == (object)null) {
  9669. if (((object)this) == (object)type.Template || ((object)this.Template) == (object)type) return true;
  9670. Identifier thisName = this.Template == null ? this.Name : this.Template.Name;
  9671. Identifier typeName = type.Template == null ? type.Name : type.Template.Name;
  9672. if (thisName == null || typeName == null || thisName.UniqueIdKey != typeName.UniqueIdKey) return false;
  9673. if (this.NodeType != type.NodeType) return false;
  9674. if (this.DeclaringType == null || type.DeclaringType == null) return false;
  9675. }
  9676. if (this.TemplateArguments == null || type.TemplateArguments == null){
  9677. if (this.DeclaringType != null && (this.TemplateArguments == null || this.TemplateArguments.Count == 0) &&
  9678. (type.TemplateArguments == null || type.TemplateArguments.Count == 0))
  9679. return this.DeclaringType.IsStructurallyEquivalentTo(type.DeclaringType);
  9680. return false;
  9681. }
  9682. int n = this.TemplateArguments.Count; if (n != type.TemplateArguments.Count) return false;
  9683. if (this.Template != type.Template && !this.Template.IsStructurallyEquivalentTo(type.Template)) return false;
  9684. for (int i = 0; i < n; i++){
  9685. TypeNode ta1 = this.TemplateArguments[i];
  9686. TypeNode ta2 = type.TemplateArguments[i];
  9687. if (null == (object)ta1 || null == (object)ta2) return false;
  9688. if (ta1 == ta2) continue;
  9689. if (!ta1.IsStructurallyEquivalentTo(ta2)) return false;
  9690. }
  9691. if (this.DeclaringType != null)
  9692. return this.DeclaringType.IsStructurallyEquivalentTo(type.DeclaringType);
  9693. return true;
  9694. }
  9695. public virtual bool IsStructurallyEquivalentList(TypeNodeList list1, TypeNodeList list2){
  9696. if (list1 == null) return list2 == null;
  9697. if (list2 == null) return false;
  9698. int n = list1.Count; if (list2.Count != n) return false;
  9699. for (int i = 0; i < n; i++){
  9700. TypeNode t1 = list1[i];
  9701. TypeNode t2 = list2[i];
  9702. if (null == (object)t1 || null == (object)t2) return false;
  9703. if (t1 == t2) continue;
  9704. if (!t1.IsStructurallyEquivalentTo(t2)) return false;
  9705. }
  9706. return true;
  9707. }
  9708. public static TypeNode StripModifiers(TypeNode type)
  9709. //^ ensures t != null ==> result != null;
  9710. {
  9711. for (TypeModifier tmod = type as TypeModifier; tmod != null; tmod = type as TypeModifier)
  9712. type = tmod.ModifiedType;
  9713. // Don't strip under pointers or refs. We only strip top-level modifiers.
  9714. return type;
  9715. }
  9716. #if !MinimalReader
  9717. public static TypeNode DeepStripModifiers(TypeNode type)
  9718. //^ ensures type != null ==> result != null;
  9719. {
  9720. // strip off any outer type modifiers
  9721. for (TypeModifier tmod = type as TypeModifier; tmod != null; tmod = type as TypeModifier)
  9722. type = tmod.ModifiedType;
  9723. // For arrays and references, strip the inner type and then reconstruct the array or reference
  9724. ArrayType ar = type as ArrayType;
  9725. if (ar != null) {
  9726. TypeNode t = TypeNode.DeepStripModifiers(ar.ElementType);
  9727. return t.GetArrayType(1);
  9728. }
  9729. Reference rt = type as Reference;
  9730. if (rt != null) {
  9731. TypeNode t = TypeNode.DeepStripModifiers(rt.ElementType);
  9732. return t.GetReferenceType();
  9733. }
  9734. return type;
  9735. }
  9736. /// <summary>
  9737. /// Strip the given modifier from the type, modulo substructures that are instantiated with respect
  9738. /// to the given template type. In other words, travers type and templateType in parallel, stripping common
  9739. /// non-null modifiers, but stop when reaching a type variable in the template type.
  9740. /// <param name="type">Type to be stripped</param>
  9741. /// <param name="modifiers">Modifiers to strip off</param>
  9742. /// <param name="templateType">Template bounding the stripping of type. Passing null for the templateType performs a full DeepStrip</param>
  9743. /// </summary>
  9744. public static TypeNode DeepStripModifiers(TypeNode type, TypeNode templateType, params TypeNode[] modifiers) {
  9745. if (templateType == null) return DeepStripModifiers(type, modifiers);
  9746. if (templateType is ITypeParameter) return type;
  9747. // strip off inner modifiers then outer type modifier if it matches
  9748. OptionalModifier optmod = type as OptionalModifier;
  9749. if (optmod != null) {
  9750. OptionalModifier optmodtemplate = (OptionalModifier)templateType; // must be in sync
  9751. TypeNode t = TypeNode.DeepStripModifiers(optmod.ModifiedType, optmodtemplate.ModifiedType, modifiers);
  9752. for (int i = 0; i < modifiers.Length; ++i) {
  9753. if (optmod.Modifier == modifiers[i]) {
  9754. // strip it
  9755. return t;
  9756. }
  9757. }
  9758. return OptionalModifier.For(optmod.Modifier, t);
  9759. }
  9760. RequiredModifier reqmod = type as RequiredModifier;
  9761. if (reqmod != null) {
  9762. RequiredModifier reqmodtemplate = (RequiredModifier)templateType; // must be in sync
  9763. TypeNode t = TypeNode.DeepStripModifiers(reqmod.ModifiedType, reqmodtemplate.ModifiedType, modifiers);
  9764. for (int i = 0; i < modifiers.Length; ++i) {
  9765. if (reqmod.Modifier == modifiers[i]) {
  9766. // strip it
  9767. return t;
  9768. }
  9769. }
  9770. return RequiredModifier.For(reqmod.Modifier, t);
  9771. }
  9772. // For arrays and references, strip the inner type and then reconstruct the array or reference
  9773. ArrayType ar = type as ArrayType;
  9774. if (ar != null) {
  9775. ArrayType artemplate = (ArrayType)templateType;
  9776. TypeNode t = TypeNode.DeepStripModifiers(ar.ElementType, artemplate.ElementType, modifiers);
  9777. return t.GetArrayType(1);
  9778. }
  9779. Reference rt = type as Reference;
  9780. if (rt != null) {
  9781. Reference rttemplate = (Reference)templateType;
  9782. TypeNode t = TypeNode.DeepStripModifiers(rt.ElementType, rttemplate.ElementType, modifiers);
  9783. return t.GetReferenceType();
  9784. }
  9785. // strip template arguments
  9786. if (type.Template != null && type.TemplateArguments != null && type.TemplateArguments.Count > 0) {
  9787. TypeNodeList strippedArgs = new TypeNodeList(type.TemplateArguments.Count);
  9788. for (int i = 0; i < type.TemplateArguments.Count; i++) {
  9789. //FIX: bug introduced by checkin 16494
  9790. //templateType may have type parameters in either the TemplateArguments position or the templateParameters position.
  9791. //This may indicate an inconsistency in the template instantiation representation elsewhere.
  9792. TypeNodeList templateTypeArgs = templateType.TemplateArguments != null ? templateType.TemplateArguments : templateType.TemplateParameters;
  9793. strippedArgs.Add(DeepStripModifiers(type.TemplateArguments[i], templateTypeArgs[i], modifiers));
  9794. }
  9795. return type.Template.GetTemplateInstance(type, strippedArgs);
  9796. }
  9797. return type;
  9798. }
  9799. public static TypeNode DeepStripModifiers(TypeNode type, params TypeNode[] modifiers) {
  9800. // strip off inner modifiers then outer type modifier if it matches
  9801. OptionalModifier optmod = type as OptionalModifier;
  9802. if (optmod != null) {
  9803. TypeNode t = TypeNode.DeepStripModifiers(optmod.ModifiedType, modifiers);
  9804. for (int i = 0; i < modifiers.Length; ++i) {
  9805. if (optmod.Modifier == modifiers[i]) {
  9806. // strip it
  9807. return t;
  9808. }
  9809. }
  9810. return OptionalModifier.For(optmod.Modifier, t);
  9811. }
  9812. RequiredModifier reqmod = type as RequiredModifier;
  9813. if (reqmod != null) {
  9814. TypeNode t = TypeNode.DeepStripModifiers(reqmod.ModifiedType, modifiers);
  9815. for (int i = 0; i < modifiers.Length; ++i) {
  9816. if (reqmod.Modifier == modifiers[i]) {
  9817. // strip it
  9818. return t;
  9819. }
  9820. }
  9821. return RequiredModifier.For(reqmod.Modifier, t);
  9822. }
  9823. // For arrays and references, strip the inner type and then reconstruct the array or reference
  9824. ArrayType ar = type as ArrayType;
  9825. if (ar != null) {
  9826. TypeNode t = TypeNode.DeepStripModifiers(ar.ElementType, modifiers);
  9827. return t.GetArrayType(1);
  9828. }
  9829. Reference rt = type as Reference;
  9830. if (rt != null) {
  9831. TypeNode t = TypeNode.DeepStripModifiers(rt.ElementType, modifiers);
  9832. return t.GetReferenceType();
  9833. }
  9834. // strip template arguments
  9835. if (type.Template != null && type.TemplateArguments != null && type.TemplateArguments.Count > 0) {
  9836. TypeNodeList strippedArgs = new TypeNodeList(type.TemplateArguments.Count);
  9837. for (int i = 0; i < type.TemplateArguments.Count; i++) {
  9838. strippedArgs.Add(DeepStripModifiers(type.TemplateArguments[i], modifiers));
  9839. }
  9840. return type.Template.GetTemplateInstance(type, strippedArgs);
  9841. }
  9842. return type;
  9843. }
  9844. #endif
  9845. public static bool HasModifier(TypeNode type, TypeNode modifier) {
  9846. // Don't look under pointers or refs.
  9847. TypeModifier tmod = type as TypeModifier;
  9848. if (tmod != null) {
  9849. if (tmod.Modifier == modifier) return true;
  9850. return TypeNode.HasModifier(tmod.ModifiedType, modifier);
  9851. }
  9852. return false;
  9853. }
  9854. public static TypeNode StripModifier(TypeNode type, TypeNode modifier) {
  9855. // Don't strip under pointers or refs. We only strip top-level modifiers
  9856. TypeModifier tmod = type as TypeModifier;
  9857. if (tmod != null){
  9858. TypeNode et = TypeNode.StripModifier(tmod.ModifiedType, modifier);
  9859. //^ assert et != null;
  9860. if (tmod.Modifier == modifier) return et;
  9861. if (et == tmod.ModifiedType) return tmod;
  9862. if (tmod is OptionalModifier) return OptionalModifier.For(tmod.Modifier, et);
  9863. return RequiredModifier.For(tmod.Modifier, et);
  9864. }
  9865. return type;
  9866. }
  9867. /// <summary>
  9868. /// Needed whenever we change the id of an existing member
  9869. /// </summary>
  9870. #if !MinimalReader
  9871. public
  9872. #else
  9873. internal
  9874. #endif
  9875. virtual void ClearMemberTable() {
  9876. lock(this) {
  9877. this.memberTable = null;
  9878. this.memberCount = 0;
  9879. }
  9880. }
  9881. protected virtual void UpdateMemberTable(int range)
  9882. //^ ensures this.memberTable != null;
  9883. {
  9884. MemberList thisMembers = this.Members;
  9885. lock(this){
  9886. if (this.memberTable == null) this.memberTable = new TrivialHashtable(32);
  9887. for (int i = this.memberCount; i < range; i++){
  9888. Member mem = thisMembers[i];
  9889. if (mem == null || mem.Name == null) continue;
  9890. MemberList members = (MemberList)this.memberTable[mem.Name.UniqueIdKey];
  9891. if (members == null) this.memberTable[mem.Name.UniqueIdKey] = members = new MemberList();
  9892. members.Add(mem);
  9893. }
  9894. this.memberCount = range;
  9895. this.constructors = null;
  9896. }
  9897. }
  9898. protected static MemberList WeedOutNonSpecialMethods(MemberList members, MethodFlags mask){
  9899. if (members == null) return null;
  9900. bool membersOK = true;
  9901. for (int i = 0, n = members.Count; i < n; i++){
  9902. Method m = members[i] as Method;
  9903. if (m == null || (m.Flags & mask) == 0){
  9904. membersOK = false; break;
  9905. }
  9906. }
  9907. if (membersOK) return members;
  9908. MemberList newMembers = new MemberList();
  9909. for (int i = 0, n = members.Count; i < n; i++){
  9910. Method m = members[i] as Method;
  9911. if (m == null || (m.Flags & mask) == 0) continue;
  9912. newMembers.Add(m);
  9913. }
  9914. return newMembers;
  9915. }
  9916. #if !NoXml
  9917. public override void WriteDocumentation(XmlTextWriter xwriter){
  9918. base.WriteDocumentation(xwriter);
  9919. MemberList members = this.Members;
  9920. for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++){
  9921. Member mem = members[i];
  9922. if (mem == null) continue;
  9923. mem.WriteDocumentation(xwriter);
  9924. }
  9925. }
  9926. #endif
  9927. #if ExtendedRuntime
  9928. public TypeNode StripOptionalModifiers(out bool nonNull){
  9929. TypeNode t = this;
  9930. nonNull = false;
  9931. for(;;){
  9932. OptionalModifier m = t as OptionalModifier;
  9933. if (m == null)
  9934. break;
  9935. if (m.Modifier == SystemTypes.NonNullType)
  9936. nonNull = true;
  9937. t = m.ModifiedType;
  9938. }
  9939. return t;
  9940. }
  9941. public bool IsObjectReferenceType{
  9942. get{
  9943. bool nonNull;
  9944. TypeNode t = this.StripOptionalModifiers(out nonNull);
  9945. return t is Class || t is Interface || t is ArrayType || t is DelegateNode;
  9946. }
  9947. }
  9948. #endif
  9949. public override string ToString() {
  9950. #if !FxCop
  9951. return this.GetFullUnmangledNameWithTypeParameters();
  9952. #else
  9953. return base.ToString() + ":" + this.GetFullUnmangledNameWithTypeParameters();
  9954. #endif
  9955. }
  9956. #if FxCop
  9957. internal override void GetName(MemberFormat options, StringBuilder name)
  9958. {
  9959. GetName(options.Type, name);
  9960. }
  9961. internal virtual void GetName(TypeFormat options, StringBuilder name)
  9962. {
  9963. if (options.TypeName != TypeNameFormat.None)
  9964. {
  9965. if (this.DeclaringType != null && options.TypeName != TypeNameFormat.InnermostNested)
  9966. {
  9967. this.DeclaringType.GetName(options, name);
  9968. name.Append('+');
  9969. }
  9970. else if (options.TypeName == TypeNameFormat.FullyQualified && this.Namespace.Name.Length > 0)
  9971. {
  9972. name.Append(this.Namespace.Name);
  9973. name.Append('.');
  9974. }
  9975. string shortName = this.Name.Name;
  9976. int mangleChar = shortName.IndexOf(TargetPlatform.GenericTypeNamesMangleChar);
  9977. if (mangleChar != -1)
  9978. shortName = shortName.Substring(0, mangleChar);
  9979. name.Append(shortName);
  9980. }
  9981. TypeNodeList templateParameters = this.TemplateParameters;
  9982. if (this.Template != null) templateParameters = this.TemplateArguments;
  9983. if (templateParameters != null)
  9984. {
  9985. if (options.ShowGenericTypeArity)
  9986. {
  9987. name.Append(TargetPlatform.GenericTypeNamesMangleChar);
  9988. int parametersCount = templateParameters.Count;
  9989. name.Append(Convert.ToString(parametersCount, CultureInfo.InvariantCulture));
  9990. }
  9991. if (options.ShowGenericTypeParameterNames)
  9992. {
  9993. name.Append('<');
  9994. int parametersCount = templateParameters.Count;
  9995. for (int i = 0; i < parametersCount; ++i)
  9996. {
  9997. if (i > 0)
  9998. {
  9999. name.Append(',');
  10000. if (options.InsertSpacesBetweenTypeParameters) name.Append(' ');
  10001. }
  10002. templateParameters[i].GetName(options, name);
  10003. }
  10004. name.Append('>');
  10005. }
  10006. }
  10007. }
  10008. #endif
  10009. }
  10010. #if FxCop
  10011. public class ClassNode : TypeNode{
  10012. #else
  10013. public class Class : TypeNode{
  10014. #endif
  10015. internal readonly static Class DoesNotExist = new Class();
  10016. internal readonly static Class Dummy = new Class();
  10017. internal Class baseClass;
  10018. #if !MinimalReader
  10019. public Class BaseClassExpression;
  10020. public bool IsAbstractSealedContainerForStatics;
  10021. #endif
  10022. #if FxCop
  10023. public ClassNode()
  10024. : base(NodeType.Class){
  10025. }
  10026. public ClassNode(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  10027. : base(NodeType.Class, provideNestedTypes, provideAttributes, provideMembers, handle){
  10028. }
  10029. #else
  10030. public Class()
  10031. : base(NodeType.Class){
  10032. }
  10033. public Class(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  10034. : base(NodeType.Class, provideNestedTypes, provideAttributes, provideMembers, handle){
  10035. }
  10036. #endif
  10037. #if !MinimalReader
  10038. public Class(Module declaringModule, TypeNode declaringType, AttributeList attributes, TypeFlags flags,
  10039. Identifier Namespace, Identifier name, Class baseClass, InterfaceList interfaces, MemberList members)
  10040. : base(declaringModule, declaringType, attributes, flags, Namespace, name, interfaces, members, NodeType.Class){
  10041. this.baseClass = baseClass;
  10042. }
  10043. #endif
  10044. /// <summary>
  10045. /// The class from which this class has been derived. Null if this class is System.Object.
  10046. /// </summary>
  10047. public virtual Class BaseClass{
  10048. get{
  10049. return baseClass;
  10050. }
  10051. set{
  10052. baseClass = value;
  10053. }
  10054. }
  10055. #if !MinimalReader
  10056. public override void GetAbstractMethods(MethodList/*!*/ result) {
  10057. if (!this.IsAbstract) return;
  10058. MethodList candidates = new MethodList();
  10059. if (this.BaseClass != null){
  10060. this.BaseClass.GetAbstractMethods(candidates);
  10061. for (int i = 0, n = candidates.Count; i < n; i++){
  10062. Method meth = candidates[i];
  10063. if (!this.ImplementsMethod(meth, false)) result.Add(meth);
  10064. }
  10065. }
  10066. //Add any abstract methods declared inside this class
  10067. MemberList members = this.Members;
  10068. for (int i = 0, n = members.Count; i < n; i++){
  10069. Method meth = members[i] as Method;
  10070. if (meth == null) continue;
  10071. if (meth.IsAbstract) result.Add(meth);
  10072. }
  10073. //For each interface, get abstract methods and keep those that are not implemented by this class or a base class
  10074. InterfaceList interfaces = this.Interfaces;
  10075. if (interfaces != null)
  10076. for (int i = 0, n = interfaces.Count; i < n; i++){
  10077. Interface iface = interfaces[i];
  10078. if (iface == null) continue;
  10079. MemberList imembers = iface.Members;
  10080. if (imembers == null) continue;
  10081. for (int j = 0, m = imembers.Count; j < m; j++){
  10082. Method meth = imembers[j] as Method;
  10083. if (meth == null) continue;
  10084. if (this.ImplementsExplicitly(meth)) continue;
  10085. if (this.ImplementsMethod(meth,true)) continue;
  10086. if (this.AlreadyInList(result, meth)) continue;
  10087. result.Add(meth);
  10088. }
  10089. }
  10090. }
  10091. protected bool AlreadyInList(MethodList list, Method method){
  10092. if (list == null) return false;
  10093. for (int i = 0, n = list.Count; i < n; i++){
  10094. if (list[i] == method) return true;
  10095. }
  10096. return false;
  10097. }
  10098. #endif
  10099. #if ExtendedRuntime
  10100. public bool IsGuarded{
  10101. get{
  10102. Field f = this.GetField(Identifier.For("SpecSharp::frameGuard"));
  10103. return f != null;
  10104. }
  10105. }
  10106. #endif
  10107. }
  10108. #if !MinimalReader
  10109. public class ClosureClass : Class{
  10110. public ClosureClass(){
  10111. }
  10112. }
  10113. /// <summary>
  10114. /// Does not model a real type, but leverages the symbol table methods of Class. In other words, this is implementation inheritance, not an ISA relationship.
  10115. /// </summary>
  10116. //TODO: use delegation rather than inheritance to achieve this
  10117. public class Scope : Class{
  10118. public Scope(){
  10119. }
  10120. public Scope(Scope outerScope){
  10121. this.OuterScope = outerScope;
  10122. }
  10123. protected Scope outerScope;
  10124. public SourceContext LexicalSourceExtent;
  10125. public Scope OuterScope{
  10126. get{
  10127. if (this.outerScope == null)
  10128. this.outerScope = (Scope)this.baseClass;
  10129. return this.outerScope;
  10130. }
  10131. set{
  10132. this.baseClass = this.outerScope = value;
  10133. }
  10134. }
  10135. public virtual TypeNode GetType(Identifier typeName){
  10136. return this.GetNestedType(typeName);
  10137. }
  10138. }
  10139. public class TypeScope : Scope{
  10140. public TypeNode Type;
  10141. public TypeScope(){}
  10142. public TypeScope(Scope parentScope, TypeNode/*!*/ type) {
  10143. this.baseClass = parentScope;
  10144. this.DeclaringModule = type.DeclaringModule;
  10145. this.Type = type;
  10146. if (type != null && type.PartiallyDefines != null) this.Type = type.PartiallyDefines;
  10147. this.templateParameters = type.TemplateParameters;
  10148. if (type != null)
  10149. this.LexicalSourceExtent = type.SourceContext;
  10150. }
  10151. public override MemberList/*!*/ GetMembersNamed(Identifier name) {
  10152. TypeNode t = this.Type;
  10153. MemberList result = null;
  10154. while (t != null){
  10155. result = t.GetMembersNamed(name);
  10156. if (result.Count > 0) return result;
  10157. t = t.BaseType;
  10158. }
  10159. if (result != null) return result;
  10160. return new MemberList(0);
  10161. }
  10162. public override MemberList Members{
  10163. get{
  10164. return this.Type.Members;
  10165. }
  10166. set{
  10167. base.Members = value;
  10168. }
  10169. }
  10170. }
  10171. public class MethodScope : Scope{
  10172. protected Class closureClass;
  10173. public virtual Class ClosureClass{
  10174. get{
  10175. //if (this.DeclaringMethod == null) return null;
  10176. Class c = this.closureClass;
  10177. if (c == null){
  10178. c = this.closureClass = new ClosureClass();
  10179. c.Name = Identifier.For("closure:"+this.UniqueKey);
  10180. c.BaseClass = CoreSystemTypes.Object;
  10181. Class bclass = this.BaseClass;
  10182. c.DeclaringModule = bclass.DeclaringModule;
  10183. TypeScope tscope = bclass as TypeScope;
  10184. if (tscope != null)
  10185. c.DeclaringType = tscope.Type;
  10186. else{
  10187. MethodScope mscope = bclass as MethodScope;
  10188. if (mscope != null)
  10189. c.DeclaringType = mscope.ClosureClass;
  10190. else
  10191. c.DeclaringType = ((BlockScope)bclass).ClosureClass;
  10192. }
  10193. c.IsGeneric = c.DeclaringType.IsGeneric || this.DeclaringMethod.IsGeneric;
  10194. c.TemplateParameters = this.CopyMethodTemplateParameters(c.DeclaringModule, c.DeclaringType);
  10195. c.Flags = TypeFlags.NestedPrivate|TypeFlags.SpecialName|TypeFlags.Sealed;
  10196. c.Interfaces = new InterfaceList(0);
  10197. if (this.ThisType != null){
  10198. Field f = new Field(c, null, FieldFlags.CompilerControlled | FieldFlags.SpecialName, StandardIds.ThisValue, this.ThisType, null);
  10199. this.ThisField = f;
  10200. c.Members.Add(f);
  10201. }
  10202. }
  10203. return c;
  10204. }
  10205. }
  10206. private TypeNodeList CopyMethodTemplateParameters(Module/*!*/ module, TypeNode/*!*/ type)
  10207. //^ requires this.DeclaringMethod != null;
  10208. {
  10209. TypeNodeList methTemplParams = this.DeclaringMethod.TemplateParameters;
  10210. if (methTemplParams == null || methTemplParams.Count == 0) return null;
  10211. this.tpDup = new TemplateParameterDuplicator(module, type);
  10212. return this.tpDup.VisitTypeParameterList(methTemplParams);
  10213. }
  10214. private TemplateParameterDuplicator tpDup;
  10215. private class TemplateParameterDuplicator : Duplicator{
  10216. public TemplateParameterDuplicator(Module/*!*/ module, TypeNode/*!*/ type)
  10217. : base(module, type){
  10218. }
  10219. public override TypeNode VisitTypeParameter(TypeNode typeParameter){
  10220. if (typeParameter == null) return null;
  10221. TypeNode result = (TypeNode)this.DuplicateFor[typeParameter.UniqueKey];
  10222. if (result != null) return result;
  10223. MethodTypeParameter mtp = typeParameter as MethodTypeParameter;
  10224. if (mtp != null){
  10225. TypeParameter tp = new TypeParameter();
  10226. this.DuplicateFor[typeParameter.UniqueKey] = tp;
  10227. tp.Name = mtp.Name;
  10228. tp.Interfaces = this.VisitInterfaceReferenceList(mtp.Interfaces);
  10229. tp.TypeParameterFlags = mtp.TypeParameterFlags;
  10230. tp.DeclaringModule = mtp.DeclaringModule;
  10231. tp.DeclaringMember = this.TargetType;
  10232. result = tp;
  10233. }else{
  10234. MethodClassParameter mcp = typeParameter as MethodClassParameter;
  10235. if (mcp != null){
  10236. ClassParameter cp = new ClassParameter();
  10237. this.DuplicateFor[typeParameter.UniqueKey] = cp;
  10238. cp.Name = mcp.Name;
  10239. cp.BaseClass = (Class)this.VisitTypeReference(mcp.BaseClass);
  10240. cp.Interfaces = this.VisitInterfaceReferenceList(mcp.Interfaces);
  10241. cp.TypeParameterFlags = mcp.TypeParameterFlags;
  10242. cp.DeclaringModule = mcp.DeclaringModule;
  10243. cp.DeclaringMember = this.TargetType;
  10244. result = cp;
  10245. }
  10246. }
  10247. if (result == null) return typeParameter;
  10248. return result;
  10249. }
  10250. public override TypeNode VisitTypeReference(TypeNode type){
  10251. TypeNode result = base.VisitTypeReference(type);
  10252. if (result == type && (type is MethodClassParameter || type is MethodTypeParameter))
  10253. return this.VisitTypeParameter(type);
  10254. return result;
  10255. }
  10256. }
  10257. public virtual Class ClosureClassTemplateInstance {
  10258. get{
  10259. if (this.closureClassTemplateInstance == null) {
  10260. if (this.DeclaringMethod == null || !this.DeclaringMethod.IsGeneric)
  10261. this.closureClassTemplateInstance = this.ClosureClass;
  10262. else
  10263. this.closureClassTemplateInstance = (Class)this.ClosureClass.GetTemplateInstance(this.DeclaringMethod.DeclaringType, this.DeclaringMethod.TemplateParameters);
  10264. }
  10265. return this.closureClassTemplateInstance;
  10266. }
  10267. }
  10268. Class closureClassTemplateInstance;
  10269. public TypeNode FixTypeReference(TypeNode type) {
  10270. if (this.tpDup == null) return type;
  10271. return this.tpDup.VisitTypeReference(type);
  10272. }
  10273. public virtual Boolean CapturedForClosure{
  10274. get{
  10275. return this.closureClass != null;
  10276. }
  10277. }
  10278. public UsedNamespaceList UsedNamespaces;
  10279. public Field ThisField;
  10280. public TypeNode ThisType;
  10281. public TypeNode ThisTypeInstance;
  10282. public Method DeclaringMethod;
  10283. public MethodScope(){}
  10284. public MethodScope(Class/*!*/ parentScope, UsedNamespaceList usedNamespaces)
  10285. : this(parentScope, usedNamespaces, null){
  10286. }
  10287. public MethodScope(Class/*!*/ parentScope, UsedNamespaceList usedNamespaces, Method method) {
  10288. this.baseClass = parentScope;
  10289. this.UsedNamespaces = usedNamespaces;
  10290. this.DeclaringModule = parentScope.DeclaringModule;
  10291. this.DeclaringMethod = method;
  10292. if (method != null && (method.Flags & MethodFlags.Static) == 0)
  10293. this.ThisType = this.ThisTypeInstance = method.DeclaringType;
  10294. if (method != null)
  10295. this.LexicalSourceExtent = method.SourceContext;
  10296. }
  10297. }
  10298. public class BlockScope : Scope{
  10299. public Block AssociatedBlock;
  10300. public bool MembersArePinned;
  10301. public virtual Class ClosureClass{
  10302. get{
  10303. BlockScope bscope = this.BaseClass as BlockScope;
  10304. if (bscope != null) return bscope.ClosureClass;
  10305. MethodScope mscope = this.BaseClass as MethodScope;
  10306. if (mscope != null) return mscope.ClosureClass;
  10307. return ((TypeScope)this.BaseClass).Type as Class;
  10308. }
  10309. }
  10310. public virtual Boolean CapturedForClosure{
  10311. get{
  10312. BlockScope bscope = this.BaseClass as BlockScope;
  10313. if (bscope != null) return bscope.CapturedForClosure;
  10314. MethodScope mscope = this.BaseClass as MethodScope;
  10315. if (mscope != null) return mscope.CapturedForClosure;
  10316. return false;
  10317. }
  10318. }
  10319. public BlockScope(){
  10320. }
  10321. public BlockScope(Scope/*!*/ parentScope, Block associatedBlock) {
  10322. this.AssociatedBlock = associatedBlock;
  10323. if (associatedBlock != null){
  10324. associatedBlock.HasLocals = true; //TODO: set only if there really are locals
  10325. associatedBlock.Scope = this;
  10326. }
  10327. this.baseClass = parentScope;
  10328. this.DeclaringModule = parentScope.DeclaringModule;
  10329. if (associatedBlock != null)
  10330. this.LexicalSourceExtent = associatedBlock.SourceContext;
  10331. }
  10332. }
  10333. public class AttributeScope : Scope{
  10334. public AttributeNode AssociatedAttribute;
  10335. public AttributeScope(Scope parentScope, AttributeNode associatedAttribute){
  10336. this.AssociatedAttribute = associatedAttribute;
  10337. this.baseClass = parentScope;
  10338. if (associatedAttribute != null)
  10339. this.LexicalSourceExtent = associatedAttribute.SourceContext;
  10340. }
  10341. }
  10342. public class NamespaceScope : Scope{
  10343. public Namespace AssociatedNamespace;
  10344. public Module AssociatedModule;
  10345. public TrivialHashtable AliasedType;
  10346. public TrivialHashtable AliasedNamespace;
  10347. protected TrivialHashtable/*!*/ aliasFor = new TrivialHashtable();
  10348. protected TrivialHashtable/*!*/ typeFor = new TrivialHashtable();
  10349. protected TrivialHashtable/*!*/ namespaceFor = new TrivialHashtable();
  10350. protected TrivialHashtable/*!*/ nestedNamespaceFullName = new TrivialHashtable();
  10351. protected readonly static AliasDefinition/*!*/ noSuchAlias = new AliasDefinition();
  10352. public NamespaceScope(){
  10353. }
  10354. public NamespaceScope(Scope outerScope, Namespace associatedNamespace, Module associatedModule)
  10355. : base(outerScope){
  10356. //^ base;
  10357. this.AssociatedNamespace = associatedNamespace;
  10358. this.AssociatedModule = associatedModule;
  10359. this.DeclaringModule = associatedModule; //TODO: make this go away
  10360. if (associatedNamespace != null)
  10361. this.LexicalSourceExtent = associatedNamespace.SourceContext;
  10362. }
  10363. public virtual AliasDefinition GetAliasFor(Identifier name){
  10364. if (name == null || this.AssociatedNamespace == null || this.AssociatedModule == null || this.aliasFor == null){
  10365. Debug.Assert(false); return null;
  10366. }
  10367. AliasDefinition alias = (AliasDefinition)this.aliasFor[name.UniqueIdKey];
  10368. if (alias == noSuchAlias) return null;
  10369. if (alias != null) return alias;
  10370. //Check if there is an alias with this uri
  10371. Scope scope = this;
  10372. while (scope != null){
  10373. NamespaceScope nsScope = scope as NamespaceScope;
  10374. if (nsScope != null && nsScope.AssociatedNamespace != null){
  10375. AliasDefinitionList aliases = nsScope.AssociatedNamespace.AliasDefinitions;
  10376. if (aliases != null)
  10377. for (int i = 0, n = aliases.Count; i < n; i++){
  10378. AliasDefinition aliasDef = aliases[i];
  10379. if (aliasDef == null || aliasDef.Alias == null) continue;
  10380. if (aliasDef.Alias.UniqueIdKey == name.UniqueIdKey){alias = aliasDef; goto done;}
  10381. }
  10382. }
  10383. scope = scope.OuterScope;
  10384. }
  10385. done:
  10386. if (alias != null)
  10387. this.aliasFor[name.UniqueIdKey] = alias;
  10388. else
  10389. this.aliasFor[name.UniqueIdKey] = noSuchAlias;
  10390. return alias;
  10391. }
  10392. public virtual AliasDefinition GetConflictingAlias(Identifier name){
  10393. if (name == null || this.typeFor == null || this.AssociatedNamespace == null || this.AssociatedModule == null){
  10394. Debug.Assert(false); return null;
  10395. }
  10396. TypeNode type = this.AssociatedModule.GetType(this.AssociatedNamespace.FullNameId, name);
  10397. if (type != null) {
  10398. AliasDefinitionList aliases = this.AssociatedNamespace.AliasDefinitions;
  10399. for (int i = 0, n = aliases == null ? 0 : aliases.Count; i < n; i++){
  10400. //^ assert aliases != null;
  10401. AliasDefinition aliasDef = aliases[i];
  10402. if (aliasDef == null || aliasDef.Alias == null) continue;
  10403. if (aliasDef.Alias.UniqueIdKey == name.UniqueIdKey) return aliasDef;
  10404. }
  10405. }
  10406. Scope scope = this;
  10407. while (scope != null) {
  10408. NamespaceScope outerScope = scope.OuterScope as NamespaceScope;
  10409. if (outerScope != null) return outerScope.GetConflictingAlias(name);
  10410. scope = scope.OuterScope;
  10411. }
  10412. return null;
  10413. }
  10414. public virtual Identifier GetUriFor(Identifier name) {
  10415. AliasDefinition aliasDef = this.GetAliasFor(name);
  10416. if (aliasDef == null) return null;
  10417. return aliasDef.AliasedUri;
  10418. }
  10419. public virtual Identifier GetNamespaceFullNameFor(Identifier name){
  10420. if (name == null || this.AssociatedNamespace == null || this.AssociatedModule == null || this.nestedNamespaceFullName == null){
  10421. Debug.Assert(false); return null;
  10422. }
  10423. Identifier fullName = (Identifier)this.nestedNamespaceFullName[name.UniqueIdKey];
  10424. if (fullName == Identifier.Empty) return null;
  10425. if (fullName != null) return fullName;
  10426. //Check if there is an alias with this namespace
  10427. AliasDefinition aliasDef = this.GetAliasFor(name);
  10428. if (aliasDef != null && aliasDef.AliasedUri == null && aliasDef.AliasedType == null)
  10429. return aliasDef.AliasedExpression as Identifier;
  10430. //Check if module has a type with namespace equal to this namespace + name
  10431. fullName = name;
  10432. if (this.AssociatedNamespace.Name != null && this.AssociatedNamespace.Name.UniqueIdKey != Identifier.Empty.UniqueIdKey)
  10433. fullName = Identifier.For(this.AssociatedNamespace.FullName+"."+name);
  10434. if (this.AssociatedModule.IsValidNamespace(fullName)){
  10435. this.namespaceFor[fullName.UniqueIdKey] = new TrivialHashtable();
  10436. goto returnFullName;
  10437. }
  10438. // If an inner type shadows an outer namespace, don't return the namespace
  10439. if (this.AssociatedModule.IsValidTypeName(this.AssociatedNamespace.Name, name)) { return null; }
  10440. AssemblyReferenceList arefs = this.AssociatedModule.AssemblyReferences;
  10441. for (int i = 0, n = arefs == null ? 0 : arefs.Count; i < n; i++){
  10442. AssemblyReference ar = arefs[i];
  10443. if (ar == null || ar.Assembly == null) continue;
  10444. if (ar.Assembly.IsValidNamespace(fullName)) goto returnFullName;
  10445. // If an inner type shadows an outer namespace, don't return the namespace
  10446. if (ar.Assembly.IsValidTypeName(this.AssociatedNamespace.Name, name)) { return null; }
  10447. }
  10448. ModuleReferenceList mrefs = this.AssociatedModule.ModuleReferences;
  10449. if (mrefs != null)
  10450. for (int i = 0, n = mrefs.Count; i < n; i++){
  10451. ModuleReference mr = mrefs[i];
  10452. if (mr == null || mr.Module == null) continue;
  10453. if (mr.Module.IsValidNamespace(fullName)) goto returnFullName;
  10454. // If an inner type shadows an outer namespace, don't return the namespace
  10455. if (mr.Module.IsValidTypeName(this.AssociatedNamespace.Name, name)) { return null; }
  10456. }
  10457. Scope scope = this.OuterScope;
  10458. while (scope != null && !(scope is NamespaceScope)) scope = scope.OuterScope;
  10459. if (scope != null) return ((NamespaceScope)scope).GetNamespaceFullNameFor(name);
  10460. return null;
  10461. returnFullName:
  10462. this.nestedNamespaceFullName[name.UniqueIdKey] = fullName;
  10463. return fullName;
  10464. }
  10465. /// <summary>
  10466. /// Search this namespace for a type with this name nested in the given namespace. Also considers used name spaces.
  10467. /// If more than one type is found, a list is returned in duplicates.
  10468. /// </summary>
  10469. public virtual TypeNode GetType(Identifier Namespace, Identifier name, out TypeNodeList duplicates){
  10470. duplicates = null;
  10471. if (Namespace == null || name == null || this.AssociatedNamespace == null || this.AssociatedModule == null){
  10472. Debug.Assert(false); return null;
  10473. }
  10474. if (this.namespaceFor == null){
  10475. Debug.Assert(false);
  10476. this.namespaceFor = new TrivialHashtable();
  10477. }
  10478. TrivialHashtable typeFor = (TrivialHashtable)this.namespaceFor[Namespace.UniqueIdKey];
  10479. if (typeFor == null) this.namespaceFor[Namespace.UniqueIdKey] = typeFor = new TrivialHashtable();
  10480. TypeNode result = (TypeNode)typeFor[name.UniqueIdKey];
  10481. if (result == Class.DoesNotExist) return null;
  10482. if (result != null) return result;
  10483. //If the associated module declares a type with the given name in a nested namespace, it wins
  10484. Scope scope = this;
  10485. while (scope != null){
  10486. NamespaceScope nsScope = scope as NamespaceScope;
  10487. if (nsScope != null && nsScope.AssociatedNamespace != null){
  10488. Identifier nestedNamespace = Namespace;
  10489. if (nsScope.AssociatedNamespace.FullNameId != null && nsScope.AssociatedNamespace.FullNameId.UniqueIdKey != Identifier.Empty.UniqueIdKey)
  10490. nestedNamespace = Identifier.For(nsScope.AssociatedNamespace.FullName+"."+Namespace);
  10491. result = this.AssociatedModule.GetType(nestedNamespace, name);
  10492. if (result != null) break;
  10493. }
  10494. scope = scope.OuterScope;
  10495. }
  10496. if (result == null){
  10497. //Now get into situations where there might be duplicates.
  10498. duplicates = new TypeNodeList();
  10499. //Check the used namespaces of this and outer namespace scopes
  10500. TrivialHashtable alreadyUsed = new TrivialHashtable();
  10501. scope = this;
  10502. while (scope != null){
  10503. NamespaceScope nsScope = scope as NamespaceScope;
  10504. if (nsScope != null && nsScope.AssociatedNamespace != null){
  10505. UsedNamespaceList usedNamespaces = nsScope.AssociatedNamespace.UsedNamespaces;
  10506. int n = usedNamespaces == null ? 0 : usedNamespaces.Count;
  10507. if (usedNamespaces != null)
  10508. for (int i = 0; i < n; i++){
  10509. UsedNamespace usedNs = usedNamespaces[i];
  10510. if (usedNs == null || usedNs.Namespace == null) continue;
  10511. int key = usedNs.Namespace.UniqueIdKey;
  10512. if (alreadyUsed[key] != null) continue;
  10513. alreadyUsed[key] = usedNs.Namespace;
  10514. Identifier usedNestedNamespace = Identifier.For(usedNs.Namespace+"."+Namespace);
  10515. result = this.AssociatedModule.GetType(usedNestedNamespace, name);
  10516. if (result != null) duplicates.Add(result);
  10517. }
  10518. }
  10519. scope = scope.OuterScope;
  10520. }
  10521. if (duplicates.Count > 0) result = duplicates[0];
  10522. }
  10523. if (result == null){
  10524. //The associated module does not have a type by this name, so check its referenced modules and assemblies
  10525. int numDups = 0;
  10526. //Check this namespace and outer namespaces
  10527. scope = this;
  10528. while (scope != null && result == null){
  10529. NamespaceScope nsScope = scope as NamespaceScope;
  10530. if (nsScope != null && nsScope.AssociatedNamespace != null){
  10531. Identifier nestedNamespace = Namespace;
  10532. if (nsScope.AssociatedNamespace.FullNameId != null && nsScope.AssociatedNamespace.FullNameId.UniqueIdKey != Identifier.Empty.UniqueIdKey)
  10533. nestedNamespace = Identifier.For(nsScope.AssociatedNamespace.FullName+"."+Namespace);
  10534. nsScope.GetReferencedTypes(nestedNamespace, name, duplicates);
  10535. numDups = duplicates.Count;
  10536. for (int i = numDups-1; i >= 0; i--){
  10537. TypeNode dup = duplicates[i];
  10538. if (dup == null || !dup.IsPublic) numDups--;
  10539. result = dup;
  10540. }
  10541. }
  10542. scope = scope.OuterScope;
  10543. }
  10544. if (numDups == 0){
  10545. if (duplicates.Count > 0) duplicates = new TypeNodeList();
  10546. //Check the used namespaces of this and outer namespace scopes
  10547. TrivialHashtable alreadyUsed = new TrivialHashtable();
  10548. scope = this;
  10549. while (scope != null){
  10550. NamespaceScope nsScope = scope as NamespaceScope;
  10551. if (nsScope != null && nsScope.AssociatedNamespace != null){
  10552. UsedNamespaceList usedNamespaces = this.AssociatedNamespace.UsedNamespaces;
  10553. int n = usedNamespaces == null ? 0 : usedNamespaces.Count;
  10554. if (usedNamespaces != null)
  10555. for (int i = 0; i < n; i++){
  10556. UsedNamespace usedNs = usedNamespaces[i];
  10557. if (usedNs == null) continue;
  10558. int key = usedNs.Namespace.UniqueIdKey;
  10559. if (alreadyUsed[key] != null) continue;
  10560. alreadyUsed[key] = usedNs.Namespace;
  10561. Identifier usedNestedNamespace = Identifier.For(usedNs.Namespace+"."+Namespace);
  10562. this.GetReferencedTypes(usedNestedNamespace, name, duplicates);
  10563. }
  10564. }
  10565. scope = scope.OuterScope;
  10566. }
  10567. numDups = duplicates.Count;
  10568. for (int i = numDups-1; i >= 0; i--){
  10569. TypeNode dup = duplicates[i];
  10570. if (dup == null || !dup.IsPublic) numDups--;
  10571. result = dup;
  10572. }
  10573. }
  10574. if (numDups <= 1) duplicates = null;
  10575. }
  10576. if (result == null)
  10577. typeFor[name.UniqueIdKey] = Class.DoesNotExist;
  10578. else
  10579. typeFor[name.UniqueIdKey] = result;
  10580. return result;
  10581. }
  10582. /// <summary>
  10583. /// Searches this namespace for a type with this name. Also considers aliases and used name spaces, including those of outer namespaces.
  10584. /// If more than one type is found, a list is returned in duplicates. Types defined in the associated
  10585. /// module mask types defined in referenced modules and assemblies. Results are cached and duplicates are returned only when
  10586. /// there is a cache miss.
  10587. /// </summary>
  10588. public virtual TypeNode GetType(Identifier name, out TypeNodeList duplicates){
  10589. return this.GetType(name, out duplicates, false);
  10590. }
  10591. public virtual TypeNode GetType(Identifier name, out TypeNodeList duplicates, bool returnNullIfHiddenByNestedNamespace){
  10592. duplicates = null;
  10593. if (name == null || this.typeFor == null || this.AssociatedNamespace == null || this.AssociatedModule == null){
  10594. Debug.Assert(false); return null;
  10595. }
  10596. AssemblyNode associatedAssembly = this.AssociatedModule as AssemblyNode;
  10597. TypeNode result = (TypeNode)this.typeFor[name.UniqueIdKey];
  10598. if (result == Class.DoesNotExist) return null;
  10599. if (result != null) return result;
  10600. //If the associated module declares a type with the given name in this namespace, it wins
  10601. result = this.AssociatedModule.GetType(this.AssociatedNamespace.FullNameId, name);
  10602. if (result == null && returnNullIfHiddenByNestedNamespace){
  10603. //Do not proceed to outer namespaces or look at aliases. The nested namespace hides these.
  10604. Identifier fullName = name;
  10605. if (this.AssociatedNamespace.FullName != null && this.AssociatedNamespace.Name.UniqueIdKey != Identifier.Empty.UniqueIdKey)
  10606. fullName = Identifier.For(this.AssociatedNamespace.FullName+"."+name);
  10607. if (this.AssociatedModule.IsValidNamespace(fullName))
  10608. result = Class.DoesNotExist;
  10609. }
  10610. if (result == null){
  10611. //If the namespace (or an outer namespace) has an alias definition with this name it wins. (Expected to be mutually exclusive with above.)
  10612. Scope scope = this;
  10613. while (scope != null && result == null){
  10614. NamespaceScope nsScope = scope as NamespaceScope;
  10615. if (nsScope != null && nsScope.AliasedType != null)
  10616. result = (TypeNode)nsScope.AliasedType[name.UniqueIdKey];
  10617. if (result == null && returnNullIfHiddenByNestedNamespace && nsScope != null &&
  10618. nsScope.AliasedNamespace != null && nsScope.AliasedNamespace[name.UniqueIdKey] != null)
  10619. result = Class.DoesNotExist;
  10620. scope = scope.OuterScope;
  10621. }
  10622. }
  10623. if (result == null){
  10624. //Now get into situations where there might be duplicates.
  10625. duplicates = new TypeNodeList();
  10626. //Check the used namespaces of this and outer namespace scopes
  10627. TrivialHashtable alreadyUsed = new TrivialHashtable();
  10628. Scope scope = this;
  10629. while (scope != null) {
  10630. NamespaceScope nsScope = scope as NamespaceScope;
  10631. if (nsScope != null && nsScope.AssociatedNamespace != null && nsScope.AssociatedModule != null) {
  10632. UsedNamespaceList usedNamespaces = nsScope.AssociatedNamespace.UsedNamespaces;
  10633. int n = usedNamespaces == null ? 0 : usedNamespaces.Count;
  10634. if (usedNamespaces != null)
  10635. for (int i = 0; i < n; i++) {
  10636. UsedNamespace usedNs = usedNamespaces[i];
  10637. if (usedNs == null || usedNs.Namespace == null) continue;
  10638. int key = usedNs.Namespace.UniqueIdKey;
  10639. if (alreadyUsed[key] != null) continue;
  10640. alreadyUsed[key] = usedNs.Namespace;
  10641. result = this.AssociatedModule.GetType(usedNs.Namespace, name);
  10642. //^ assert duplicates != null;
  10643. if (result != null) duplicates.Add(result);
  10644. }
  10645. }
  10646. if (returnNullIfHiddenByNestedNamespace) break;
  10647. scope = scope.OuterScope;
  10648. }
  10649. if (duplicates.Count > 0) result = duplicates[0];
  10650. }
  10651. if (result == null)
  10652. //First see if the the current module has a class by this name in the empty namespace
  10653. result = this.AssociatedModule.GetType(Identifier.Empty, name);
  10654. if (result == null){
  10655. //The associated module does not have a type by this name, so check its referenced modules and assemblies
  10656. //First check this namespace
  10657. this.GetReferencedTypes(this.AssociatedNamespace.FullNameId, name, duplicates);
  10658. int numDups = duplicates.Count;
  10659. if (numDups == 1){
  10660. result = duplicates[0];
  10661. if (this.IsNotAccessible(associatedAssembly, result)) { numDups--; result = null; }
  10662. }else{
  10663. for (int i = numDups-1; i >= 0; i--){
  10664. TypeNode dup = duplicates[i];
  10665. if (this.IsNotAccessible(associatedAssembly, dup)) { numDups--; continue; }
  10666. result = dup;
  10667. }
  10668. if (numDups == 0 && duplicates.Count > 0){
  10669. result = duplicates[0];
  10670. numDups = duplicates.Count;
  10671. }
  10672. }
  10673. if (numDups == 0){
  10674. if (duplicates.Count > 0) duplicates = new TypeNodeList();
  10675. //Check the used namespaces of this and outer namespace scopes
  10676. TrivialHashtable alreadyUsed = new TrivialHashtable();
  10677. Scope scope = this;
  10678. while (scope != null) {
  10679. NamespaceScope nsScope = scope as NamespaceScope;
  10680. if (nsScope != null) {
  10681. UsedNamespaceList usedNamespaces = nsScope.AssociatedNamespace.UsedNamespaces;
  10682. int n = usedNamespaces == null ? 0 : usedNamespaces.Count;
  10683. if (usedNamespaces != null)
  10684. for (int i = 0; i < n; i++) {
  10685. UsedNamespace usedNs = usedNamespaces[i];
  10686. if (usedNs == null || usedNs.Namespace == null) continue;
  10687. int key = usedNs.Namespace.UniqueIdKey;
  10688. if (alreadyUsed[key] != null) continue;
  10689. alreadyUsed[key] = usedNs.Namespace;
  10690. this.GetReferencedTypes(usedNs.Namespace, name, duplicates);
  10691. }
  10692. }
  10693. scope = scope.OuterScope;
  10694. if (returnNullIfHiddenByNestedNamespace) break;
  10695. }
  10696. numDups = duplicates.Count;
  10697. for (int i = numDups-1; i >= 0; i--){
  10698. TypeNode dup = duplicates[i];
  10699. if (this.IsNotAccessible(associatedAssembly, dup)) {
  10700. numDups--; continue;
  10701. }
  10702. result = dup;
  10703. }
  10704. }
  10705. if (numDups == 0){
  10706. if (duplicates.Count > 0) duplicates = new TypeNodeList();
  10707. this.GetReferencedTypes(Identifier.Empty, name, duplicates);
  10708. numDups = duplicates.Count;
  10709. for (int i = numDups-1; i >= 0; i--){
  10710. TypeNode dup = duplicates[i];
  10711. if (this.IsNotAccessible(associatedAssembly, dup)) {
  10712. numDups--; continue;
  10713. }
  10714. result = dup;
  10715. }
  10716. }
  10717. if (numDups <= 1) duplicates = null;
  10718. }
  10719. if (result == null)
  10720. this.typeFor[name.UniqueIdKey] = Class.DoesNotExist;
  10721. else
  10722. this.typeFor[name.UniqueIdKey] = result;
  10723. if (result == Class.DoesNotExist) return null;
  10724. if (duplicates != null && duplicates.Count > 1 && this.AssociatedNamespace != null && this.AssociatedNamespace.Name != null && this.AssociatedNamespace.Name.Name != null) {
  10725. result = null;
  10726. for (int i = 0, n = duplicates.Count; i < n; i++) {
  10727. TypeNode t = duplicates[i];
  10728. if (t == null || t.Namespace == null) continue;
  10729. if (this.AssociatedNamespace.Name.Name.StartsWith(t.Namespace.Name)) {
  10730. if (result != null) {
  10731. result = null;
  10732. break;
  10733. }
  10734. result = t;
  10735. }
  10736. }
  10737. if (result != null)
  10738. duplicates = null;
  10739. else
  10740. result = duplicates[0];
  10741. }
  10742. return result;
  10743. }
  10744. private bool IsNotAccessible(AssemblyNode associatedAssembly, TypeNode dup) {
  10745. if (dup == null) return false;
  10746. return !dup.IsPublic && (associatedAssembly == null ||
  10747. !associatedAssembly.MayAccessInternalTypesOf(dup.DeclaringModule as AssemblyNode)) && !this.AssociatedModule.ContainsModule(dup.DeclaringModule);
  10748. }
  10749. /// <summary>
  10750. /// Searches the module and assembly references of the associated module to find types
  10751. /// </summary>
  10752. public virtual void GetReferencedTypes(Identifier Namespace, Identifier name, TypeNodeList types){
  10753. if (Namespace == null || name == null || types == null || this.AssociatedModule == null) {Debug.Assert(false); return;}
  10754. AssemblyReferenceList arefs = this.AssociatedModule.AssemblyReferences;
  10755. for (int i = 0, n = arefs == null ? 0 : arefs.Count; i < n; i++){
  10756. AssemblyReference ar = arefs[i];
  10757. if (ar == null || ar.Assembly == null) continue;
  10758. TypeNode t = ar.Assembly.GetType(Namespace, name);
  10759. if (t == null) continue;
  10760. //TODO: deal with type forwarding
  10761. types.Add(t);
  10762. }
  10763. ModuleReferenceList mrefs = this.AssociatedModule.ModuleReferences;
  10764. if (mrefs != null)
  10765. for (int i = 0, n = mrefs.Count; i < n; i++){
  10766. ModuleReference mr = mrefs[i];
  10767. if (mr == null || mr.Module == null) continue;
  10768. TypeNode t = mr.Module.GetType(Namespace, name);
  10769. if (t == null) continue;
  10770. types.Add(t);
  10771. }
  10772. }
  10773. }
  10774. #endif
  10775. public class DelegateNode : TypeNode{
  10776. internal static readonly DelegateNode/*!*/ Dummy = new DelegateNode();
  10777. protected ParameterList parameters;
  10778. public virtual ParameterList Parameters{
  10779. get{
  10780. ParameterList pList = this.parameters;
  10781. if (pList == null){
  10782. MemberList members = this.Members; //Evaluate for side effect
  10783. if (members != null) members = null;
  10784. lock(this){
  10785. if (this.parameters != null) return this.parameters;
  10786. MemberList invokers = this.GetMembersNamed(StandardIds.Invoke);
  10787. for (int i = 0, n = invokers.Count; i < n; i++){
  10788. Method m = invokers[i] as Method;
  10789. if (m == null) continue;
  10790. this.parameters = pList = m.Parameters;
  10791. this.returnType = m.ReturnType;
  10792. break;
  10793. }
  10794. }
  10795. }
  10796. return pList;
  10797. }
  10798. set{
  10799. this.parameters = value;
  10800. }
  10801. }
  10802. protected TypeNode returnType;
  10803. public virtual TypeNode ReturnType{
  10804. get{
  10805. TypeNode rt = this.returnType;
  10806. if (rt == null){
  10807. ParameterList pars = this.Parameters; //Evaluate for side effect
  10808. if (pars != null) pars = null;
  10809. rt = this.returnType;
  10810. }
  10811. return rt;
  10812. }
  10813. set{
  10814. this.returnType = value;
  10815. }
  10816. }
  10817. #if !MinimalReader
  10818. public TypeNode ReturnTypeExpression;
  10819. #endif
  10820. public DelegateNode()
  10821. : base(NodeType.DelegateNode){
  10822. }
  10823. public DelegateNode(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  10824. : base(NodeType.DelegateNode, provideNestedTypes, provideAttributes, provideMembers, handle){
  10825. }
  10826. #if !MinimalReader
  10827. public DelegateNode(Module declaringModule, TypeNode declaringType, AttributeList attributes, TypeFlags flags,
  10828. Identifier Namespace, Identifier name, TypeNode returnType, ParameterList parameters)
  10829. : base(declaringModule, declaringType, attributes, flags, Namespace, name, null, null, NodeType.DelegateNode){
  10830. this.parameters = parameters;
  10831. this.returnType = returnType;
  10832. }
  10833. private bool membersAlreadyProvided;
  10834. public virtual void ProvideMembers(){
  10835. if (this.membersAlreadyProvided) return;
  10836. this.membersAlreadyProvided = true;
  10837. this.memberCount = 0;
  10838. MemberList members = this.members = new MemberList();
  10839. //ctor
  10840. ParameterList parameters = new ParameterList(2);
  10841. parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.Object, CoreSystemTypes.Object, null, null));
  10842. parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.Method, CoreSystemTypes.IntPtr, null, null));
  10843. InstanceInitializer ctor = new InstanceInitializer(this, null, parameters, null);
  10844. ctor.Flags |= MethodFlags.Public|MethodFlags.HideBySig;
  10845. ctor.CallingConvention = CallingConventionFlags.HasThis;
  10846. ctor.ImplFlags = MethodImplFlags.Runtime;
  10847. members.Add(ctor);
  10848. //Invoke
  10849. Method invoke = new Method(this, null, StandardIds.Invoke, this.Parameters, this.ReturnType, null);
  10850. invoke.Flags = MethodFlags.Public|MethodFlags.HideBySig|MethodFlags.Virtual|MethodFlags.NewSlot;
  10851. invoke.CallingConvention = CallingConventionFlags.HasThis;
  10852. invoke.ImplFlags = MethodImplFlags.Runtime;
  10853. members.Add(invoke);
  10854. // Skip adding async methods if AsyncCallback is a dummy.
  10855. if (SystemTypes.AsyncCallback.ReturnType != null)
  10856. {
  10857. //BeginInvoke
  10858. ParameterList dparams = this.parameters;
  10859. int n = dparams == null ? 0 : dparams.Count;
  10860. parameters = new ParameterList(n + 2);
  10861. for (int i = 0; i < n; i++)
  10862. {
  10863. //^ assert dparams != null;
  10864. Parameter p = dparams[i];
  10865. if (p == null) continue;
  10866. parameters.Add((Parameter)p.Clone());
  10867. }
  10868. parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.callback, SystemTypes.AsyncCallback, null, null));
  10869. parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.Object, CoreSystemTypes.Object, null, null));
  10870. Method beginInvoke = new Method(this, null, StandardIds.BeginInvoke, parameters, SystemTypes.IASyncResult, null);
  10871. beginInvoke.Flags = MethodFlags.Public | MethodFlags.HideBySig | MethodFlags.NewSlot | MethodFlags.Virtual;
  10872. beginInvoke.CallingConvention = CallingConventionFlags.HasThis;
  10873. beginInvoke.ImplFlags = MethodImplFlags.Runtime;
  10874. members.Add(beginInvoke);
  10875. //EndInvoke
  10876. parameters = new ParameterList(1);
  10877. for (int i = 0; i < n; i++)
  10878. {
  10879. Parameter p = dparams[i];
  10880. if (p == null || p.Type == null || !(p.Type is Reference)) continue;
  10881. parameters.Add((Parameter)p.Clone());
  10882. }
  10883. parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.result, SystemTypes.IASyncResult, null, null));
  10884. Method endInvoke = new Method(this, null, StandardIds.EndInvoke, parameters, this.ReturnType, null);
  10885. endInvoke.Flags = MethodFlags.Public | MethodFlags.HideBySig | MethodFlags.NewSlot | MethodFlags.Virtual;
  10886. endInvoke.CallingConvention = CallingConventionFlags.HasThis;
  10887. endInvoke.ImplFlags = MethodImplFlags.Runtime;
  10888. members.Add(endInvoke);
  10889. }
  10890. if (!this.IsGeneric){
  10891. TypeNodeList templPars = this.TemplateParameters;
  10892. for (int i = 0, m = templPars == null ? 0 : templPars.Count; i < m; i++){
  10893. //^ assert templPars != null;
  10894. TypeNode tpar = templPars[i];
  10895. if (tpar == null) continue;
  10896. members.Add(tpar);
  10897. }
  10898. }
  10899. }
  10900. #endif
  10901. }
  10902. #if !MinimalReader
  10903. public class FunctionType : DelegateNode{
  10904. private FunctionType(Identifier name, TypeNode returnType, ParameterList parameters){
  10905. this.Flags = TypeFlags.Public|TypeFlags.Sealed;
  10906. this.Namespace = StandardIds.StructuralTypes;
  10907. this.Name = name;
  10908. this.returnType = returnType;
  10909. this.parameters = parameters;
  10910. }
  10911. public static FunctionType For(TypeNode returnType, ParameterList parameters, TypeNode referringType){
  10912. if (returnType == null || referringType == null) return null;
  10913. Module module = referringType.DeclaringModule;
  10914. if (module == null) return null;
  10915. TypeFlags visibility = returnType.Flags & TypeFlags.VisibilityMask;
  10916. StringBuilder name = new StringBuilder();
  10917. name.Append("Function_");
  10918. name.Append(returnType.Name.ToString());
  10919. int n = parameters == null ? 0 : parameters.Count;
  10920. if (parameters != null)
  10921. for (int i = 0; i < n; i++){
  10922. Parameter p = parameters[i];
  10923. if (p == null || p.Type == null) continue;
  10924. visibility = TypeNode.GetVisibilityIntersection(visibility, p.Type.Flags & TypeFlags.VisibilityMask);
  10925. name.Append('_');
  10926. name.Append(p.Type.Name.ToString());
  10927. }
  10928. FunctionType func = null;
  10929. int count = 0;
  10930. string fNameString = name.ToString();
  10931. Identifier fName = Identifier.For(fNameString);
  10932. TypeNode result = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, fName);
  10933. while (result != null){
  10934. //Mangled name is the same. But mangling is not unique (types are not qualified with assemblies), so check for equality.
  10935. func = result as FunctionType;
  10936. bool goodMatch = func != null && func.ReturnType == returnType;
  10937. if (goodMatch){
  10938. //^ assert func != null;
  10939. ParameterList fpars = func.Parameters;
  10940. int m = fpars == null ? 0 : fpars.Count;
  10941. goodMatch = n == m;
  10942. if (parameters != null && fpars != null)
  10943. for (int i = 0; i < n && goodMatch; i++){
  10944. Parameter p = parameters[i];
  10945. Parameter q = fpars[i];
  10946. goodMatch = p != null && q != null && p.Type == q.Type;
  10947. }
  10948. }
  10949. if (goodMatch) return func;
  10950. //Mangle some more
  10951. fName = Identifier.For(fNameString+(++count).ToString());
  10952. result = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, fName);
  10953. }
  10954. if (parameters != null){
  10955. ParameterList clonedParams = new ParameterList(n);
  10956. for (int i = 0; i < n; i++){
  10957. Parameter p = parameters[i];
  10958. if (p != null) p = (Parameter)p.Clone();
  10959. clonedParams.Add(p);
  10960. }
  10961. parameters = clonedParams;
  10962. }
  10963. func = new FunctionType(fName, returnType, parameters);
  10964. func.DeclaringModule = module;
  10965. switch (visibility){
  10966. case TypeFlags.NestedFamANDAssem:
  10967. case TypeFlags.NestedFamily:
  10968. case TypeFlags.NestedPrivate:
  10969. referringType.Members.Add(func);
  10970. func.DeclaringType = referringType;
  10971. func.Flags &= ~TypeFlags.VisibilityMask;
  10972. func.Flags |= TypeFlags.NestedPrivate;
  10973. break;
  10974. default:
  10975. module.Types.Add(func);
  10976. break;
  10977. }
  10978. module.StructurallyEquivalentType[func.Name.UniqueIdKey] = func;
  10979. func.ProvideMembers();
  10980. return func;
  10981. }
  10982. public override bool IsStructural{
  10983. get{return true;}
  10984. }
  10985. protected TypeNodeList structuralElementTypes;
  10986. public override TypeNodeList StructuralElementTypes{
  10987. get{
  10988. TypeNodeList result = this.structuralElementTypes;
  10989. if (result != null) return result;
  10990. this.structuralElementTypes = result = new TypeNodeList();
  10991. result.Add(this.ReturnType);
  10992. ParameterList pars = this.Parameters;
  10993. for (int i = 0, n = pars == null ? 0 : pars.Count; i < n; i++){
  10994. Parameter par = pars[i];
  10995. if (par == null || par.Type == null) continue;
  10996. result.Add(par.Type);
  10997. }
  10998. return result;
  10999. }
  11000. }
  11001. public override bool IsStructurallyEquivalentTo(TypeNode type){
  11002. if (type == null) return false;
  11003. if (this == type) return true;
  11004. FunctionType t = type as FunctionType;
  11005. if (t == null) return false;
  11006. if (this.Template != null) return base.IsStructurallyEquivalentTo(t);
  11007. if (this.Flags != t.Flags) return false;
  11008. if (this.ReturnType == null || t.ReturnType == null) return false;
  11009. if (this.ReturnType != t.ReturnType && !this.ReturnType.IsStructurallyEquivalentTo(t.ReturnType)) return false;
  11010. if (this.Parameters == null) return t.Parameters == null;
  11011. if (t.Parameters == null) return false;
  11012. int n = this.Parameters.Count; if (n != t.Parameters.Count) return false;
  11013. for (int i = 0; i < n; i++){
  11014. Parameter p1 = this.Parameters[i];
  11015. Parameter p2 = t.Parameters[i];
  11016. if (p1 == null || p2 == null) return false;
  11017. if (p1.Type == null || p2.Type == null) return false;
  11018. if (p1.Type != p2.Type && !p1.Type.IsStructurallyEquivalentTo(p2.Type)) return false;
  11019. }
  11020. return true;
  11021. }
  11022. }
  11023. #endif
  11024. public class EnumNode : TypeNode{
  11025. internal readonly static EnumNode/*!*/ Dummy = new EnumNode();
  11026. public EnumNode()
  11027. : base(NodeType.EnumNode){
  11028. this.typeCode = ElementType.ValueType;
  11029. this.Flags |= TypeFlags.Sealed;
  11030. }
  11031. public EnumNode(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  11032. : base(NodeType.EnumNode, provideNestedTypes, provideAttributes, provideMembers, handle){
  11033. this.typeCode = ElementType.ValueType;
  11034. this.Flags |= TypeFlags.Sealed;
  11035. }
  11036. #if !MinimalReader
  11037. public EnumNode(Module declaringModule, TypeNode declaringType, AttributeList attributes, TypeFlags typeAttributes,
  11038. Identifier Namespace, Identifier name, InterfaceList interfaces, MemberList members)
  11039. : base(declaringModule, declaringType, attributes, typeAttributes, Namespace, name, interfaces, members, NodeType.EnumNode){
  11040. this.typeCode = ElementType.ValueType;
  11041. this.Flags |= TypeFlags.Sealed;
  11042. }
  11043. #endif
  11044. public override bool IsUnmanaged{
  11045. get{
  11046. return true;
  11047. }
  11048. }
  11049. protected internal TypeNode underlyingType;
  11050. /// <summary>
  11051. /// The underlying integer type used to store values of this enumeration.
  11052. /// </summary>
  11053. public virtual TypeNode UnderlyingType{
  11054. get{
  11055. if (this.underlyingType == null){
  11056. if (this.template is EnumNode)
  11057. return this.underlyingType = ((EnumNode)this.template).UnderlyingType;
  11058. this.underlyingType = CoreSystemTypes.Int32;
  11059. MemberList members = this.Members;
  11060. for (int i = 0, n = members.Count; i < n; i++){
  11061. Member mem = members[i];
  11062. Field f = mem as Field;
  11063. if (f != null && (f.Flags & FieldFlags.Static) == 0)
  11064. return this.underlyingType = f.Type;
  11065. }
  11066. }
  11067. return this.underlyingType;
  11068. }
  11069. set{
  11070. this.underlyingType = value;
  11071. MemberList members = this.Members;
  11072. for (int i = 0, n = members.Count; i < n; i++){
  11073. Member mem = members[i];
  11074. Field f = mem as Field;
  11075. if (f != null && (f.Flags & FieldFlags.Static) == 0){
  11076. f.Type = value;
  11077. return;
  11078. }
  11079. }
  11080. this.Members.Add(new Field(this, null, FieldFlags.Public|FieldFlags.SpecialName|FieldFlags.RTSpecialName, StandardIds.Value__, value, null));
  11081. }
  11082. }
  11083. #if ExtendedRuntime
  11084. public override bool IsPointerFree
  11085. {
  11086. get
  11087. {
  11088. return true;
  11089. }
  11090. }
  11091. #endif
  11092. #if !MinimalReader
  11093. public TypeNode UnderlyingTypeExpression;
  11094. #endif
  11095. }
  11096. #if FxCop
  11097. public class InterfaceNode : TypeNode{
  11098. #else
  11099. public class Interface : TypeNode{
  11100. #endif
  11101. protected TrivialHashtable jointMemberTable;
  11102. protected MemberList jointDefaultMembers;
  11103. internal static readonly Interface/*!*/ Dummy = new Interface();
  11104. #if FxCop
  11105. public InterfaceNode()
  11106. : base(NodeType.Interface){
  11107. this.Flags = TypeFlags.Interface|TypeFlags.Abstract;
  11108. }
  11109. public InterfaceNode(InterfaceList baseInterfaces)
  11110. : base(NodeType.Interface){
  11111. this.Interfaces = baseInterfaces;
  11112. this.Flags = TypeFlags.Interface|TypeFlags.Abstract;
  11113. }
  11114. public InterfaceNode(InterfaceList baseInterfaces, NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  11115. : base(NodeType.Interface, provideNestedTypes, provideAttributes, provideMembers, handle){
  11116. this.Interfaces = baseInterfaces;
  11117. }
  11118. #else
  11119. public Interface()
  11120. : base(NodeType.Interface){
  11121. this.Flags = TypeFlags.Interface|TypeFlags.Abstract;
  11122. }
  11123. public Interface(InterfaceList baseInterfaces)
  11124. : base(NodeType.Interface){
  11125. this.Interfaces = baseInterfaces;
  11126. this.Flags = TypeFlags.Interface|TypeFlags.Abstract;
  11127. }
  11128. public Interface(InterfaceList baseInterfaces, NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  11129. : base(NodeType.Interface, provideNestedTypes, provideAttributes, provideMembers, handle){
  11130. this.Interfaces = baseInterfaces;
  11131. }
  11132. #endif
  11133. #if !MinimalReader
  11134. public Interface(Module declaringModule, TypeNode declaringType, AttributeList attributes, TypeFlags flags,
  11135. Identifier Namespace, Identifier name, InterfaceList baseInterfaces, MemberList members)
  11136. : base(declaringModule, declaringType, attributes, flags, Namespace, name, baseInterfaces, members, NodeType.Interface){
  11137. this.Flags |= TypeFlags.Interface|TypeFlags.Abstract;
  11138. }
  11139. public override void GetAbstractMethods(MethodList/*!*/ result) {
  11140. MemberList members = this.Members;
  11141. if (members == null) return;
  11142. for (int i = 0, n = members.Count; i < n; i++){
  11143. Method m = members[i] as Method;
  11144. if (m != null) result.Add(m);
  11145. }
  11146. }
  11147. public virtual MemberList GetAllDefaultMembers() {
  11148. if (this.jointDefaultMembers == null) {
  11149. this.jointDefaultMembers = new MemberList();
  11150. MemberList defs = this.DefaultMembers;
  11151. for (int i = 0, n = defs == null ? 0 : defs.Count; i < n; i++)
  11152. this.jointDefaultMembers.Add(defs[i]);
  11153. InterfaceList interfaces = this.Interfaces;
  11154. if (interfaces != null)
  11155. for (int j = 0, m = interfaces.Count; j < m; j++) {
  11156. Interface iface = interfaces[j];
  11157. if (iface == null) continue;
  11158. defs = iface.GetAllDefaultMembers();
  11159. if (defs == null) continue;
  11160. for (int i = 0, n = defs.Count; i < n; i++)
  11161. this.jointDefaultMembers.Add(defs[i]);
  11162. }
  11163. }
  11164. return this.jointDefaultMembers;
  11165. }
  11166. public virtual MemberList GetAllMembersNamed(Identifier/*!*/ name) {
  11167. lock (this){
  11168. TrivialHashtable memberTable = this.jointMemberTable;
  11169. if (memberTable == null) this.jointMemberTable = memberTable = new TrivialHashtable();
  11170. MemberList result = (MemberList)memberTable[name.UniqueIdKey];
  11171. if (result != null) return result;
  11172. memberTable[name.UniqueIdKey] = result = new MemberList();
  11173. MemberList members = this.GetMembersNamed(name);
  11174. for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++)
  11175. result.Add(members[i]);
  11176. InterfaceList interfaces = this.Interfaces;
  11177. for (int j = 0, m = interfaces == null ? 0 : interfaces.Count; j < m; j++){
  11178. Interface iface = interfaces[j];
  11179. if (iface == null) continue;
  11180. members = iface.GetAllMembersNamed(name);
  11181. if (members != null)
  11182. for (int i = 0, n = members.Count; i < n; i++)
  11183. result.Add(members[i]);
  11184. }
  11185. members = CoreSystemTypes.Object.GetMembersNamed(name);
  11186. for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++)
  11187. result.Add(members[i]);
  11188. return result;
  11189. }
  11190. }
  11191. #endif
  11192. }
  11193. public class Struct : TypeNode{
  11194. internal static readonly Struct/*!*/ Dummy = new Struct();
  11195. public Struct()
  11196. : base(NodeType.Struct){
  11197. this.typeCode = ElementType.ValueType;
  11198. this.Flags = TypeFlags.Sealed;
  11199. }
  11200. public Struct(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  11201. : base(NodeType.Struct, provideNestedTypes, provideAttributes, provideMembers, handle){
  11202. this.typeCode = ElementType.ValueType;
  11203. }
  11204. #if !MinimalReader
  11205. public Struct(Module declaringModule, TypeNode declaringType, AttributeList attributes, TypeFlags flags,
  11206. Identifier Namespace, Identifier name, InterfaceList interfaces, MemberList members)
  11207. : base(declaringModule, declaringType, attributes, flags, Namespace, name, interfaces, members, NodeType.Struct){
  11208. this.Interfaces = interfaces;
  11209. this.typeCode = ElementType.ValueType;
  11210. this.Flags |= TypeFlags.Sealed;
  11211. }
  11212. protected bool cachedUnmanaged;
  11213. protected bool cachedUnmanagedIsValid;
  11214. /// <summary>True if the type is a value type containing only fields of unmanaged types.</summary>
  11215. public override bool IsUnmanaged{
  11216. get{
  11217. if (this.cachedUnmanagedIsValid) return this.cachedUnmanaged;
  11218. this.cachedUnmanagedIsValid = true; //protect against cycles
  11219. this.cachedUnmanaged = true; //Self references should not influence the answer
  11220. if (this.IsPrimitive) return this.cachedUnmanaged = true;
  11221. MemberList members = this.Members;
  11222. bool isUnmanaged = true;
  11223. for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++){
  11224. Field f = members[i] as Field;
  11225. if (f == null || f.Type == null || f.IsStatic) continue;
  11226. if (!f.Type.IsUnmanaged){isUnmanaged = false; break;}
  11227. }
  11228. #if ExtendedRuntime
  11229. this.cachedUnmanaged = isUnmanaged || IsPointerFree;
  11230. #else
  11231. this.cachedUnmanaged = isUnmanaged;
  11232. #endif
  11233. return this.cachedUnmanaged;
  11234. }
  11235. }
  11236. #endif
  11237. #if ExtendedRuntime
  11238. protected bool cachedPointerFree;
  11239. protected bool cachedPointerFreeIsValid;
  11240. /// <summary>True if the type is a value type containing no managed or unmanaged pointers.</summary>
  11241. public override bool IsPointerFree
  11242. {
  11243. get
  11244. {
  11245. if (this.cachedPointerFreeIsValid) return this.cachedPointerFree;
  11246. // Note: not threadsafe
  11247. this.cachedPointerFreeIsValid = true; //protect against cycles
  11248. this.cachedPointerFree = true; //Self references should not influence the answer
  11249. if (this.IsPrimitive) return this.cachedPointerFree = true;
  11250. MemberList members = this.Members;
  11251. bool isPointerFree = true;
  11252. for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++)
  11253. {
  11254. Field f = members[i] as Field;
  11255. if (f == null || f.Type == null || f.IsStatic) continue;
  11256. if (!f.Type.IsPointerFree) { isPointerFree = false; break; }
  11257. }
  11258. return this.cachedPointerFree = isPointerFree;
  11259. }
  11260. }
  11261. #endif
  11262. }
  11263. public interface ITypeParameter{
  11264. Member DeclaringMember{get;set;}
  11265. /// <summary>
  11266. /// Zero based index into a parameter list containing this parameter.
  11267. /// </summary>
  11268. int ParameterListIndex{get;set;}
  11269. TypeParameterFlags TypeParameterFlags{get;set;}
  11270. bool IsUnmanaged { get; }
  11271. #if ExtendedRuntime
  11272. bool IsPointerFree { get; }
  11273. #endif
  11274. #if !MinimalReader
  11275. Identifier Name { get; }
  11276. Module DeclaringModule { get; }
  11277. TypeNode DeclaringType { get; }
  11278. SourceContext SourceContext { get; }
  11279. int UniqueKey { get; }
  11280. TypeFlags Flags { get; }
  11281. #endif
  11282. }
  11283. public class TypeParameter : Interface, ITypeParameter{
  11284. public TypeParameter()
  11285. : base(){
  11286. this.NodeType = NodeType.TypeParameter;
  11287. this.Flags = TypeFlags.Interface|TypeFlags.NestedPublic|TypeFlags.Abstract;
  11288. this.Namespace = StandardIds.TypeParameter;
  11289. }
  11290. public TypeParameter(InterfaceList baseInterfaces, NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  11291. : base(baseInterfaces, provideNestedTypes, provideAttributes, provideMembers, handle){
  11292. this.NodeType = NodeType.TypeParameter;
  11293. this.Flags = TypeFlags.Interface|TypeFlags.NestedPublic|TypeFlags.Abstract;
  11294. this.Namespace = StandardIds.TypeParameter;
  11295. }
  11296. public Member DeclaringMember{
  11297. get{return this.declaringMember;}
  11298. set{this.declaringMember = value;}
  11299. }
  11300. private Member declaringMember;
  11301. #if !NoReflection && WHIDBEY
  11302. public override Type GetRuntimeType() {
  11303. TypeNode t = this.DeclaringMember as TypeNode;
  11304. if (t == null) return null;
  11305. Type rt = t.GetRuntimeType();
  11306. if (rt == null) return null;
  11307. System.Type[] typeParameters = rt.GetGenericArguments();
  11308. if (this.ParameterListIndex >= typeParameters.Length) return null;
  11309. return typeParameters[this.ParameterListIndex];
  11310. }
  11311. #endif
  11312. /// <summary>
  11313. /// Zero based index into a parameter list containing this parameter.
  11314. /// </summary>
  11315. public int ParameterListIndex{
  11316. get{return this.parameterListIndex;}
  11317. set{this.parameterListIndex = value;}
  11318. }
  11319. private int parameterListIndex;
  11320. #if ExtendedRuntime
  11321. private bool typeParameterFlagsIsValid = false;
  11322. #endif
  11323. public TypeParameterFlags TypeParameterFlags{
  11324. get{
  11325. #if ExtendedRuntime
  11326. if (!typeParameterFlagsIsValid) {
  11327. // check if we have the corresponding attribute
  11328. for (int i=0; i < (this.Attributes == null?0:this.Attributes.Count); i++) {
  11329. if (this.Attributes[i].Type == SystemTypes.TemplateParameterFlagsAttribute) {
  11330. Literal lit = this.Attributes[i].Expressions[0] as Literal;
  11331. if (lit != null && lit.Value is int) {
  11332. this.typeParameterFlags = (TypeParameterFlags)((int)lit.Value);
  11333. }
  11334. break;
  11335. }
  11336. }
  11337. this.typeParameterFlagsIsValid = true;
  11338. }
  11339. #endif
  11340. return this.typeParameterFlags;
  11341. }
  11342. set{
  11343. this.typeParameterFlags = value;
  11344. #if ExtendedRuntime
  11345. this.typeParameterFlagsIsValid = true;
  11346. #endif
  11347. }
  11348. }
  11349. private TypeParameterFlags typeParameterFlags;
  11350. public override bool IsStructural{
  11351. get{return true;}
  11352. }
  11353. /// <summary>True if the type serves as a parameter to a type template.</summary>
  11354. public override bool IsTemplateParameter{
  11355. get{
  11356. return true;
  11357. }
  11358. }
  11359. public override bool IsValueType {
  11360. get {
  11361. return ((this.TypeParameterFlags & TypeParameterFlags.ValueTypeConstraint) == TypeParameterFlags.ValueTypeConstraint);
  11362. }
  11363. }
  11364. #if ExtendedRuntime
  11365. public override bool IsReferenceType {
  11366. get {
  11367. return ((this.TypeParameterFlags & TypeParameterFlags.ReferenceTypeConstraint) == TypeParameterFlags.ReferenceTypeConstraint);
  11368. }
  11369. }
  11370. private bool isUnmanagedIsValid = false;
  11371. private bool isUnmanaged = false;
  11372. public override bool IsUnmanaged{
  11373. get{
  11374. if (!isUnmanagedIsValid && SystemTypes.UnmanagedStructTemplateParameterAttribute != null){
  11375. // check if we have the corresponding attribute
  11376. for (int i=0; i < (this.Attributes == null?0:this.Attributes.Count); i++){
  11377. AttributeNode attr = this.Attributes[i];
  11378. if (attr == null) continue;
  11379. if (attr.Type == SystemTypes.UnmanagedStructTemplateParameterAttribute){
  11380. isUnmanaged = true;
  11381. break;
  11382. }
  11383. #if ExtendedRuntime
  11384. if (!isUnmanaged) { isUnmanaged = IsPointerFree; }
  11385. #endif
  11386. }
  11387. isUnmanagedIsValid = true;
  11388. }
  11389. return isUnmanaged;
  11390. }
  11391. }
  11392. public void SetIsUnmanaged(){
  11393. this.isUnmanaged = true;
  11394. this.isUnmanagedIsValid = true;
  11395. }
  11396. private bool isPointerFreeIsValid = false;
  11397. private bool isPointerFree = false;
  11398. public override bool IsPointerFree
  11399. {
  11400. get
  11401. {
  11402. if (!isPointerFreeIsValid && SystemTypes.PointerFreeStructTemplateParameterAttribute != null)
  11403. {
  11404. // check if we have the corresponding attribute
  11405. for (int i = 0; i < (this.Attributes == null ? 0 : this.Attributes.Count); i++)
  11406. {
  11407. AttributeNode attr = this.Attributes[i];
  11408. if (attr == null) continue;
  11409. if (attr.Type == SystemTypes.PointerFreeStructTemplateParameterAttribute)
  11410. {
  11411. isPointerFree = true;
  11412. break;
  11413. }
  11414. }
  11415. isPointerFreeIsValid = true;
  11416. }
  11417. return isPointerFree;
  11418. }
  11419. }
  11420. public void SetIsPointerFree()
  11421. {
  11422. this.isPointerFree = true;
  11423. this.isPointerFreeIsValid = true;
  11424. // implies unmanaged
  11425. SetIsUnmanaged();
  11426. }
  11427. #endif
  11428. #if !NoXml
  11429. public override XmlNode Documentation{
  11430. get{
  11431. if (this.documentation == null && this.declaringMember != null && this.Name != null){
  11432. XmlNode parentDoc = this.declaringMember.Documentation;
  11433. if (parentDoc != null && parentDoc.HasChildNodes){
  11434. string myName = this.Name.Name;
  11435. foreach (XmlNode child in parentDoc.ChildNodes){
  11436. if (child.Name == "typeparam" && child.Attributes != null){
  11437. foreach (XmlAttribute attr in child.Attributes){
  11438. if (attr != null && attr.Name == "name" && attr.Value == myName)
  11439. return this.documentation = child;
  11440. }
  11441. }
  11442. }
  11443. }
  11444. }
  11445. return this.documentation;
  11446. }
  11447. set{
  11448. this.documentation = value;
  11449. }
  11450. }
  11451. public override string HelpText{
  11452. get{
  11453. if (this.helpText == null){
  11454. XmlNode doc = this.Documentation;
  11455. if (doc != null) this.helpText = doc.InnerText;
  11456. }
  11457. return this.helpText;
  11458. }
  11459. set{
  11460. this.helpText = value;
  11461. }
  11462. }
  11463. #endif
  11464. protected internal TypeNodeList structuralElementTypes;
  11465. public override TypeNodeList StructuralElementTypes{
  11466. get{
  11467. TypeNodeList result = this.structuralElementTypes;
  11468. if (result != null) return result;
  11469. this.structuralElementTypes = result = new TypeNodeList();
  11470. if (this.BaseType != null) result.Add(this.BaseType);
  11471. InterfaceList interfaces = this.Interfaces;
  11472. for (int i = 0, n = interfaces == null ? 0 : interfaces.Count; i < n; i++){
  11473. Interface iface = interfaces[i];
  11474. if (iface == null) continue;
  11475. result.Add(iface);
  11476. }
  11477. return result;
  11478. }
  11479. }
  11480. #if !NoXml
  11481. internal override void AppendDocumentIdMangledName(StringBuilder/*!*/ sb, TypeNodeList methodTypeParameters, TypeNodeList typeParameters) {
  11482. if (TargetPlatform.GenericTypeNamesMangleChar != 0) {
  11483. int n = methodTypeParameters == null ? 0 : methodTypeParameters.Count;
  11484. for (int i = 0; i < n; i++){
  11485. //^ assert methodTypeParameters != null;
  11486. TypeNode mpar = methodTypeParameters[i];
  11487. if (mpar != this) continue;
  11488. sb.Append(TargetPlatform.GenericTypeNamesMangleChar);
  11489. sb.Append(TargetPlatform.GenericTypeNamesMangleChar);
  11490. sb.Append(i);
  11491. return;
  11492. }
  11493. n = typeParameters == null ? 0 : typeParameters.Count;
  11494. for (int i = 0; i < n; i++){
  11495. TypeNode tpar = typeParameters[i];
  11496. if (tpar != this) continue;
  11497. sb.Append(TargetPlatform.GenericTypeNamesMangleChar);
  11498. sb.Append(i);
  11499. return;
  11500. }
  11501. sb.Append("not found:");
  11502. }
  11503. sb.Append(this.FullName);
  11504. }
  11505. #endif
  11506. public override string GetFullUnmangledNameWithoutTypeParameters(){
  11507. return this.GetUnmangledNameWithoutTypeParameters();
  11508. }
  11509. public override string GetFullUnmangledNameWithTypeParameters(){
  11510. return this.GetUnmangledNameWithTypeParameters();
  11511. }
  11512. public override bool IsStructurallyEquivalentTo(TypeNode type){
  11513. if (null == (object)type) return false;
  11514. if (this == type) return true;
  11515. ITypeParameter itype = type as ITypeParameter;
  11516. if (null == (object)itype) return false;
  11517. if (this.Name != null && type.Name != null && this.Name.UniqueIdKey != type.Name.UniqueIdKey) {
  11518. if (this.DeclaringMember == itype.DeclaringMember) return false;
  11519. }
  11520. TypeNode bType = this.BaseType;
  11521. TypeNode tbType = type.BaseType;
  11522. if (null == (object)bType) bType = CoreSystemTypes.Object;
  11523. if (null == (object)tbType) tbType = CoreSystemTypes.Object;
  11524. if (bType != tbType /*&& !bType.IsStructurallyEquivalentTo(tbType)*/) return false;
  11525. if (this.Interfaces == null) return type.Interfaces == null || type.Interfaces.Count == 0;
  11526. if (type.Interfaces == null) return this.Interfaces.Count == 0;
  11527. int n = this.Interfaces.Count; if (n != type.Interfaces.Count) return false;
  11528. for (int i = 0; i < n; i++){
  11529. Interface i1 = this.Interfaces[i];
  11530. Interface i2 = type.Interfaces[i];
  11531. if (null == (object)i1 || null == (object)i2) return false;
  11532. if (i1 != i2 /*&& !i1.IsStructurallyEquivalentTo(i2)*/) return false;
  11533. }
  11534. return true;
  11535. }
  11536. #if !MinimalReader
  11537. Module ITypeParameter.DeclaringModule { get { return this.DeclaringModule; } }
  11538. TypeFlags ITypeParameter.Flags { get { return this.Flags; } }
  11539. SourceContext ITypeParameter.SourceContext { get { return this.SourceContext; } }
  11540. #endif
  11541. #if FxCop
  11542. internal override void GetName(TypeFormat options, StringBuilder name)
  11543. {
  11544. if (options.TypeName == TypeNameFormat.FullyQualified)
  11545. {
  11546. TypeFormat typeFormat = options.Clone();
  11547. typeFormat.TypeName = TypeNameFormat.Short;
  11548. base.GetName(typeFormat, name);
  11549. return;
  11550. }
  11551. base.GetName(options, name);
  11552. }
  11553. #endif
  11554. }
  11555. public class MethodTypeParameter : TypeParameter{
  11556. public MethodTypeParameter()
  11557. : base(){
  11558. this.NodeType = NodeType.TypeParameter;
  11559. this.Flags = TypeFlags.Interface|TypeFlags.NestedPublic|TypeFlags.Abstract;
  11560. this.Namespace = StandardIds.TypeParameter;
  11561. }
  11562. #if !MinimalReader
  11563. public MethodTypeParameter(InterfaceList baseInterfaces, NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  11564. : base(baseInterfaces, provideNestedTypes, provideAttributes, provideMembers, handle) {
  11565. this.NodeType = NodeType.TypeParameter;
  11566. this.Flags = TypeFlags.Interface|TypeFlags.NestedPublic|TypeFlags.Abstract;
  11567. this.Namespace = StandardIds.TypeParameter;
  11568. }
  11569. #endif
  11570. #if !NoReflection
  11571. #if WHIDBEY
  11572. public override Type GetRuntimeType() {
  11573. Method m = this.DeclaringMember as Method;
  11574. if (m == null) return null;
  11575. System.Reflection.MethodInfo mi = m.GetMethodInfo();
  11576. if (mi == null) return null;
  11577. System.Type[] typeParameters = mi.GetGenericArguments();
  11578. if (this.ParameterListIndex >= typeParameters.Length) return null;
  11579. return typeParameters[this.ParameterListIndex];
  11580. }
  11581. #endif
  11582. #endif
  11583. public override bool IsStructurallyEquivalentTo(TypeNode type) {
  11584. if (object.ReferenceEquals(this, type)) return true;
  11585. ITypeParameter tp = type as ITypeParameter;
  11586. if (tp == null) return false;
  11587. if (this.ParameterListIndex == tp.ParameterListIndex && this.DeclaringMember == tp.DeclaringMember) return true;
  11588. return base.IsStructurallyEquivalentTo(type as MethodTypeParameter);
  11589. }
  11590. }
  11591. public class ClassParameter : Class, ITypeParameter{
  11592. protected TrivialHashtable jointMemberTable;
  11593. public ClassParameter()
  11594. : base(){
  11595. this.NodeType = NodeType.ClassParameter;
  11596. this.baseClass = CoreSystemTypes.Object;
  11597. this.Flags = TypeFlags.NestedPublic|TypeFlags.Abstract;
  11598. this.Namespace = StandardIds.TypeParameter;
  11599. }
  11600. public ClassParameter(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  11601. : base(provideNestedTypes, provideAttributes, provideMembers, handle){
  11602. this.NodeType = NodeType.ClassParameter;
  11603. this.baseClass = CoreSystemTypes.Object;
  11604. this.Flags = TypeFlags.NestedPrivate|TypeFlags.Abstract|TypeFlags.SpecialName;
  11605. this.Namespace = StandardIds.TypeParameter;
  11606. }
  11607. public Member DeclaringMember{
  11608. get{return this.declaringMember;}
  11609. set{this.declaringMember = value;}
  11610. }
  11611. private Member declaringMember;
  11612. #if !MinimalReader
  11613. public virtual MemberList GetAllMembersNamed(Identifier/*!*/ name) {
  11614. lock (this) {
  11615. TrivialHashtable memberTable = this.jointMemberTable;
  11616. if (memberTable == null) this.jointMemberTable = memberTable = new TrivialHashtable();
  11617. MemberList result = (MemberList)memberTable[name.UniqueIdKey];
  11618. if (result != null) return result;
  11619. memberTable[name.UniqueIdKey] = result = new MemberList();
  11620. TypeNode t = this;
  11621. while (t != null) {
  11622. MemberList members = t.GetMembersNamed(name);
  11623. if (members != null)
  11624. for (int i = 0, n = members.Count; i < n; i++)
  11625. result.Add(members[i]);
  11626. t = t.BaseType;
  11627. }
  11628. InterfaceList interfaces = this.Interfaces;
  11629. if (interfaces != null)
  11630. for (int j = 0, m = interfaces.Count; j < m; j++) {
  11631. Interface iface = interfaces[j];
  11632. if (iface == null) continue;
  11633. members = iface.GetAllMembersNamed(name);
  11634. if (members != null)
  11635. for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++)
  11636. result.Add(members[i]);
  11637. }
  11638. members = CoreSystemTypes.Object.GetMembersNamed(name);
  11639. if (members != null)
  11640. for (int i = 0, n = members.Count; i < n; i++)
  11641. result.Add(members[i]);
  11642. return result;
  11643. }
  11644. }
  11645. #endif
  11646. #if !NoReflection && WHIDBEY
  11647. public override Type GetRuntimeType() {
  11648. TypeNode t = this.DeclaringMember as TypeNode;
  11649. if (t == null) return null;
  11650. Type rt = t.GetRuntimeType();
  11651. if (rt == null) return null;
  11652. System.Type[] typeParameters = rt.GetGenericArguments();
  11653. if (this.ParameterListIndex >= typeParameters.Length) return null;
  11654. return typeParameters[this.ParameterListIndex];
  11655. }
  11656. #endif
  11657. /// <summary>
  11658. /// Zero based index into a parameter list containing this parameter.
  11659. /// </summary>
  11660. public int ParameterListIndex{
  11661. get{return this.parameterListIndex;}
  11662. set{this.parameterListIndex = value;}
  11663. }
  11664. private int parameterListIndex;
  11665. public TypeParameterFlags TypeParameterFlags{
  11666. get{return this.typeParameterFlags;}
  11667. set{this.typeParameterFlags = value;}
  11668. }
  11669. private TypeParameterFlags typeParameterFlags;
  11670. public override bool IsValueType {
  11671. get {
  11672. return ((this.typeParameterFlags & TypeParameterFlags.ValueTypeConstraint) == TypeParameterFlags.ValueTypeConstraint);
  11673. }
  11674. }
  11675. public override bool IsStructural {
  11676. get{return true;}
  11677. }
  11678. /// <summary>True if the type serves as a parameter to a type template.</summary>
  11679. public override bool IsTemplateParameter{
  11680. get{
  11681. return true;
  11682. }
  11683. }
  11684. #if ExtendedRuntime
  11685. public override bool IsReferenceType {
  11686. get {
  11687. return ((this.TypeParameterFlags & TypeParameterFlags.ReferenceTypeConstraint) == TypeParameterFlags.ReferenceTypeConstraint)
  11688. || (this.baseClass != null && this.baseClass.IsReferenceType);
  11689. }
  11690. }
  11691. private bool isUnmanagedIsValid = false;
  11692. private bool isUnmanaged = false;
  11693. public override bool IsUnmanaged{
  11694. get{
  11695. if (!isUnmanagedIsValid && SystemTypes.UnmanagedStructTemplateParameterAttribute != null){
  11696. // check if we have the corresponding attribute
  11697. for (int i=0; i < (this.Attributes == null?0:this.Attributes.Count); i++){
  11698. if (this.Attributes[i].Type == SystemTypes.UnmanagedStructTemplateParameterAttribute){
  11699. isUnmanaged = true;
  11700. break;
  11701. }
  11702. }
  11703. #if ExtendedRuntime
  11704. if (!isUnmanaged) { isUnmanaged = IsPointerFree; }
  11705. #endif
  11706. isUnmanagedIsValid = true;
  11707. }
  11708. return isUnmanaged;
  11709. }
  11710. }
  11711. public void SetIsUnmanaged(){
  11712. this.isUnmanaged = true;
  11713. this.isUnmanagedIsValid = true;
  11714. }
  11715. private bool isPointerFreeIsValid = false;
  11716. private bool isPointerFree = false;
  11717. public override bool IsPointerFree
  11718. {
  11719. get
  11720. {
  11721. if (!isPointerFreeIsValid && SystemTypes.PointerFreeStructTemplateParameterAttribute != null)
  11722. {
  11723. // check if we have the corresponding attribute
  11724. for (int i = 0; i < (this.Attributes == null ? 0 : this.Attributes.Count); i++)
  11725. {
  11726. if (this.Attributes[i].Type == SystemTypes.PointerFreeStructTemplateParameterAttribute)
  11727. {
  11728. isPointerFree = true;
  11729. break;
  11730. }
  11731. }
  11732. isPointerFreeIsValid = true;
  11733. }
  11734. return isPointerFree;
  11735. }
  11736. }
  11737. public void SetIsPointerFree()
  11738. {
  11739. this.isPointerFree = true;
  11740. this.isPointerFreeIsValid = true;
  11741. // pointerfree implies Unmanaged
  11742. SetIsUnmanaged();
  11743. }
  11744. #endif
  11745. #if !NoXml
  11746. public override XmlNode Documentation{
  11747. get{
  11748. if (this.documentation == null && this.declaringMember != null && this.Name != null){
  11749. XmlNode parentDoc = this.declaringMember.Documentation;
  11750. if (parentDoc != null && parentDoc.HasChildNodes){
  11751. string myName = this.Name.Name;
  11752. foreach (XmlNode child in parentDoc.ChildNodes){
  11753. if (child.Name == "typeparam" && child.Attributes != null){
  11754. foreach (XmlAttribute attr in child.Attributes){
  11755. if (attr != null && attr.Name == "name" && attr.Value == myName)
  11756. return this.documentation = child;
  11757. }
  11758. }
  11759. }
  11760. }
  11761. }
  11762. return this.documentation;
  11763. }
  11764. set{
  11765. this.documentation = value;
  11766. }
  11767. }
  11768. public override string HelpText{
  11769. get{
  11770. if (this.helpText == null){
  11771. XmlNode doc = this.Documentation;
  11772. if (doc != null) this.helpText = doc.InnerText;
  11773. }
  11774. return this.helpText;
  11775. }
  11776. set{
  11777. this.helpText = value;
  11778. }
  11779. }
  11780. #endif
  11781. protected internal TypeNodeList structuralElementTypes;
  11782. public override TypeNodeList StructuralElementTypes{
  11783. get{
  11784. TypeNodeList result = this.structuralElementTypes;
  11785. if (result != null) return result;
  11786. this.structuralElementTypes = result = new TypeNodeList();
  11787. if (this.BaseType != null) result.Add(this.BaseType);
  11788. InterfaceList interfaces = this.Interfaces;
  11789. for (int i = 0, n = interfaces == null ? 0 : interfaces.Count; i < n; i++){
  11790. Interface iface = interfaces[i];
  11791. if (iface == null) continue;
  11792. result.Add(iface);
  11793. }
  11794. return result;
  11795. }
  11796. }
  11797. #if !NoXml
  11798. internal override void AppendDocumentIdMangledName(StringBuilder/*!*/ sb, TypeNodeList methodTypeParameters, TypeNodeList typeParameters) {
  11799. if (TargetPlatform.GenericTypeNamesMangleChar != 0) {
  11800. int n = methodTypeParameters == null ? 0 : methodTypeParameters.Count;
  11801. for (int i = 0; i < n; i++){
  11802. //^ assert methodTypeParameters != null;
  11803. TypeNode mpar = methodTypeParameters[i];
  11804. if (mpar != this) continue;
  11805. sb.Append(TargetPlatform.GenericTypeNamesMangleChar);
  11806. sb.Append(TargetPlatform.GenericTypeNamesMangleChar);
  11807. sb.Append(i);
  11808. return;
  11809. }
  11810. n = typeParameters == null ? 0 : typeParameters.Count;
  11811. for (int i = 0; i < n; i++){
  11812. TypeNode tpar = typeParameters[i];
  11813. if (tpar != this) continue;
  11814. sb.Append(TargetPlatform.GenericTypeNamesMangleChar);
  11815. sb.Append(i);
  11816. return;
  11817. }
  11818. sb.Append("not found:");
  11819. }
  11820. sb.Append(this.FullName);
  11821. }
  11822. #endif
  11823. public override string GetFullUnmangledNameWithoutTypeParameters(){
  11824. return this.GetUnmangledNameWithoutTypeParameters();
  11825. }
  11826. public override string GetFullUnmangledNameWithTypeParameters(){
  11827. return this.GetUnmangledNameWithTypeParameters();
  11828. }
  11829. public override bool IsStructurallyEquivalentTo(TypeNode type){
  11830. if (null == (object)type) return false;
  11831. if (this == type) return true;
  11832. ITypeParameter itype = type as ITypeParameter;
  11833. if (null == (object)itype) return false;
  11834. if (this.Name != null && type.Name != null && this.Name.UniqueIdKey != type.Name.UniqueIdKey){
  11835. if (this.DeclaringMember == itype.DeclaringMember) return false;
  11836. }
  11837. TypeNode bType = this.BaseType;
  11838. TypeNode tbType = type.BaseType;
  11839. if (null == (object)bType) bType = CoreSystemTypes.Object;
  11840. if (null == (object)tbType) tbType = CoreSystemTypes.Object;
  11841. if (bType != tbType /*&& !bType.IsStructurallyEquivalentTo(tbType)*/) return false;
  11842. if (this.Interfaces == null) return type.Interfaces == null || type.Interfaces.Count == 0;
  11843. if (type.Interfaces == null) return this.Interfaces.Count == 0;
  11844. int n = this.Interfaces.Count; if (n != type.Interfaces.Count) return false;
  11845. for (int i = 0; i < n; i++){
  11846. Interface i1 = this.Interfaces[i];
  11847. Interface i2 = type.Interfaces[i];
  11848. if (null == (object)i1 || null == (object)i2) return false;
  11849. if (i1 != i2 /*&& !i1.IsStructurallyEquivalentTo(i2)*/) return false;
  11850. }
  11851. return true;
  11852. }
  11853. #if !MinimalReader
  11854. SourceContext ITypeParameter.SourceContext { get { return this.SourceContext; } }
  11855. Module ITypeParameter.DeclaringModule { get { return this.DeclaringModule; } }
  11856. TypeFlags ITypeParameter.Flags { get { return this.Flags; } }
  11857. #endif
  11858. #if FxCop
  11859. internal override void GetName(TypeFormat options, StringBuilder name)
  11860. {
  11861. if (options.TypeName == TypeNameFormat.FullyQualified)
  11862. {
  11863. TypeFormat typeFormat = options.Clone();
  11864. typeFormat.TypeName = TypeNameFormat.Short;
  11865. base.GetName(typeFormat, name);
  11866. return;
  11867. }
  11868. base.GetName(options, name);
  11869. }
  11870. #endif
  11871. }
  11872. public class MethodClassParameter : ClassParameter{
  11873. public MethodClassParameter()
  11874. : base(){
  11875. this.NodeType = NodeType.ClassParameter;
  11876. this.baseClass = CoreSystemTypes.Object;
  11877. this.Flags = TypeFlags.NestedPublic|TypeFlags.Abstract;
  11878. this.Namespace = StandardIds.TypeParameter;
  11879. }
  11880. #if !NoReflection && WHIDBEY
  11881. public override Type GetRuntimeType() {
  11882. Method m = this.DeclaringMember as Method;
  11883. if (m == null) return null;
  11884. System.Reflection.MethodInfo mi = m.GetMethodInfo();
  11885. if (mi == null) return null;
  11886. System.Type[] typeParameters = mi.GetGenericArguments();
  11887. if (this.ParameterListIndex >= typeParameters.Length) return null;
  11888. return typeParameters[this.ParameterListIndex];
  11889. }
  11890. #endif
  11891. #if !MinimalReader
  11892. public override bool IsStructurallyEquivalentTo(TypeNode type) {
  11893. if (object.ReferenceEquals(this, type)) return true;
  11894. ITypeParameter tp = type as ITypeParameter;
  11895. if (tp == null) return false;
  11896. if (this.ParameterListIndex == tp.ParameterListIndex /* && this.DeclaringMember == tp.DeclaringMember*/) return true;
  11897. return base.IsStructurallyEquivalentTo(type as MethodClassParameter);
  11898. }
  11899. #endif
  11900. }
  11901. public class ArrayType : TypeNode{
  11902. private TypeNode/*!*/ elementType;
  11903. private int rank;
  11904. private int[] lowerBounds;
  11905. private int[] sizes;
  11906. internal ArrayType()
  11907. : base(NodeType.ArrayType){
  11908. }
  11909. internal ArrayType(TypeNode/*!*/ elementType, int rank)
  11910. : this(elementType, rank, new int[0], new int[0]){
  11911. if (rank == 1)
  11912. this.typeCode = Metadata.ElementType.SzArray;
  11913. else
  11914. this.typeCode = Metadata.ElementType.Array;
  11915. }
  11916. internal ArrayType(TypeNode/*!*/ elementType, int rank, int[] sizes)
  11917. : this(elementType, rank, sizes, new int[0]){
  11918. }
  11919. internal ArrayType(TypeNode/*!*/ elementType, int rank, int[] sizes, int[] lowerBounds)
  11920. : base(null, null, null, elementType.Flags, null, null, null, null, NodeType.ArrayType){
  11921. Debug.Assert(elementType != null);
  11922. this.rank = rank;
  11923. this.elementType = elementType;
  11924. this.DeclaringModule = elementType.DeclaringModule;
  11925. this.lowerBounds = lowerBounds;
  11926. this.sizes = sizes;
  11927. if (rank == 1)
  11928. this.typeCode = Metadata.ElementType.SzArray;
  11929. else
  11930. this.typeCode = Metadata.ElementType.Array;
  11931. if (elementType == null || elementType.Name == null) return;
  11932. StringBuilder name = new StringBuilder(this.ElementType.Name.ToString());
  11933. #if FxCop
  11934. GetNameSuffix(name, false);
  11935. #else
  11936. name.Append('[');
  11937. int k = this.Sizes == null ? 0 : this.Sizes.Length;
  11938. int m = this.LowerBounds == null ? 0 : this.LowerBounds.Length;
  11939. for (int i = 0, n = this.Rank; i < n; i++){
  11940. if (i < k && this.Sizes[i] != 0){
  11941. if (i < m && this.LowerBounds[i] != 0){
  11942. name.Append(this.LowerBounds[i]);
  11943. name.Append(':');
  11944. }
  11945. name.Append(this.Sizes[i]);
  11946. }
  11947. if (i < n-1)
  11948. name.Append(',');
  11949. }
  11950. name.Append(']');
  11951. #endif
  11952. this.Name = Identifier.For(name.ToString());
  11953. this.Namespace = elementType.Namespace;
  11954. }
  11955. public TypeNode/*!*/ ElementType {
  11956. get{return this.elementType;}
  11957. set{this.elementType = value;}
  11958. }
  11959. /// <summary>The interfaces implemented by this class or struct, or the extended by this interface.</summary>
  11960. public override InterfaceList Interfaces {
  11961. get {
  11962. if (this.interfaces == null) {
  11963. InterfaceList interfaces = new InterfaceList(SystemTypes.ICloneable, SystemTypes.IList, SystemTypes.ICollection, SystemTypes.IEnumerable);
  11964. if (this.Rank == 1) {
  11965. if (SystemTypes.GenericIEnumerable != null && SystemTypes.GenericIEnumerable.DeclaringModule == CoreSystemTypes.SystemAssembly) {
  11966. interfaces.Add((Interface)SystemTypes.GenericIEnumerable.GetTemplateInstance(this, elementType));
  11967. if (SystemTypes.GenericICollection != null)
  11968. interfaces.Add((Interface)SystemTypes.GenericICollection.GetTemplateInstance(this, elementType));
  11969. if (SystemTypes.GenericIList != null)
  11970. interfaces.Add((Interface)SystemTypes.GenericIList.GetTemplateInstance(this, elementType));
  11971. }
  11972. }
  11973. this.interfaces = interfaces;
  11974. }
  11975. return this.interfaces;
  11976. }
  11977. set { this.interfaces = value; }
  11978. }
  11979. public int Rank {
  11980. get{return this.rank;}
  11981. set{this.rank = value;}
  11982. }
  11983. public int[] LowerBounds{
  11984. get{return this.lowerBounds;}
  11985. set{this.lowerBounds = value;}
  11986. }
  11987. public int[] Sizes{
  11988. get{return this.sizes;}
  11989. set{this.sizes = value;}
  11990. }
  11991. public bool IsSzArray(){
  11992. return this.typeCode == Metadata.ElementType.SzArray;
  11993. }
  11994. private MemberList ctorList = null;
  11995. private MemberList getterList = null;
  11996. private MemberList setterList = null;
  11997. private MemberList addressList = null;
  11998. public override MemberList Members{
  11999. get{
  12000. if (this.members == null || this.membersBeingPopulated){
  12001. lock(this){
  12002. if (this.members == null){
  12003. this.membersBeingPopulated = true;
  12004. MemberList members = this.members = new MemberList(5);
  12005. members.Add(this.Constructor);
  12006. //^ assume this.ctorList != null && this.ctorList.Length > 1;
  12007. members.Add(this.ctorList[1]);
  12008. members.Add(this.Getter);
  12009. members.Add(this.Setter);
  12010. members.Add(this.Address);
  12011. this.membersBeingPopulated = false;
  12012. }
  12013. }
  12014. }
  12015. return this.members;
  12016. }
  12017. set{
  12018. this.members = value;
  12019. }
  12020. }
  12021. public override string/*!*/ FullName {
  12022. get{
  12023. if (this.ElementType != null && this.ElementType.DeclaringType != null)
  12024. return this.ElementType.DeclaringType.FullName+"+"+(this.Name == null ? "" : this.Name.ToString());
  12025. else if (this.Namespace != null && this.Namespace.UniqueIdKey != Identifier.Empty.UniqueIdKey)
  12026. return this.Namespace.ToString() + "."+(this.Name == null ? "" : this.Name.ToString());
  12027. else if (this.Name != null)
  12028. return this.Name.ToString();
  12029. else
  12030. return "";
  12031. }
  12032. }
  12033. #if !NoXml
  12034. internal override void AppendDocumentIdMangledName(StringBuilder/*!*/ sb, TypeNodeList methodTypeParameters, TypeNodeList typeParameters) {
  12035. if (this.ElementType == null) return;
  12036. this.ElementType.AppendDocumentIdMangledName(sb, methodTypeParameters, typeParameters);
  12037. sb.Append('[');
  12038. int k = this.Sizes == null ? 0 : this.Sizes.Length;
  12039. int m = this.LowerBounds == null ? 0 : this.LowerBounds.Length;
  12040. for (int i = 0, n = this.Rank; i < n; i++){
  12041. if (i < k && this.Sizes[i] != 0){
  12042. if (i < m && this.LowerBounds[i] != 0){
  12043. sb.Append(this.LowerBounds[i]);
  12044. sb.Append(':');
  12045. }
  12046. sb.Append(this.Sizes[i]);
  12047. }
  12048. if (i < n-1)
  12049. sb.Append(',');
  12050. }
  12051. sb.Append(']');
  12052. }
  12053. #endif
  12054. public virtual void SetLowerBoundToUnknown(){
  12055. Debug.Assert(this.Rank == 1);
  12056. this.typeCode = Metadata.ElementType.Array;
  12057. }
  12058. public virtual int GetLowerBound(int dimension){
  12059. if (this.LowerBounds == null || this.LowerBounds.Length <= dimension) return 0;
  12060. return this.LowerBounds[dimension];
  12061. }
  12062. public virtual int GetSize(int dimension){
  12063. if (this.Sizes == null || this.Sizes.Length <= dimension) return 0;
  12064. return this.Sizes[dimension];
  12065. }
  12066. public override MemberList/*!*/ GetMembersNamed(Identifier name) {
  12067. if (name == null) return new MemberList(0);
  12068. if (name.UniqueIdKey == StandardIds.Get.UniqueIdKey){
  12069. if (this.getterList == null){
  12070. Method getter = this.Getter;
  12071. if (getter != null) getter = null;
  12072. //^ assume this.getterList != null;
  12073. }
  12074. return this.getterList;
  12075. }else if (name.UniqueIdKey == StandardIds.Set.UniqueIdKey){
  12076. if (this.setterList == null){
  12077. Method setter = this.Setter;
  12078. if (setter != null) setter = null;
  12079. //^ assume this.setterList != null;
  12080. }
  12081. return this.setterList;
  12082. }else if (name.UniqueIdKey == StandardIds.Ctor.UniqueIdKey){
  12083. if (this.ctorList == null){
  12084. Method ctor = this.Constructor;
  12085. if (ctor != null) ctor = null;
  12086. //^ assume this.ctorList != null;
  12087. }
  12088. return this.ctorList;
  12089. }else if (name.UniqueIdKey == StandardIds.Address.UniqueIdKey){
  12090. if (this.addressList == null){
  12091. Method addr = this.Address;
  12092. if (addr != null) addr = null;
  12093. //^ assume this.addressList != null;
  12094. }
  12095. return this.addressList;
  12096. }else
  12097. return new MemberList(0);
  12098. }
  12099. #if !NoReflection
  12100. public override Type GetRuntimeType(){
  12101. if (this.runtimeType == null){
  12102. if (this.ElementType == null) return null;
  12103. Type eType = this.ElementType.GetRuntimeType();
  12104. if (eType == null) return null;
  12105. #if WHIDBEY
  12106. if (this.IsSzArray())
  12107. this.runtimeType = eType.MakeArrayType();
  12108. else
  12109. this.runtimeType = eType.MakeArrayType(this.Rank);
  12110. #else
  12111. StringBuilder sb = new StringBuilder(eType.FullName);
  12112. sb.Append('[');
  12113. for (int i = 1, n = this.Rank; i < n; i++) sb.Append(',');
  12114. sb.Append(']');
  12115. if (eType.Assembly != null)
  12116. this.runtimeType = eType.Assembly.GetType(sb.ToString(), false);
  12117. else if (eType.Module != null)
  12118. this.runtimeType = eType.Module.GetType(sb.ToString(), false);
  12119. #endif
  12120. }
  12121. return this.runtimeType;
  12122. }
  12123. #endif
  12124. public Method Constructor{
  12125. get{
  12126. if (this.ctorList == null){
  12127. lock(this){
  12128. if (this.ctorList == null){
  12129. InstanceInitializer ctor = new InstanceInitializer();
  12130. ctor.DeclaringType = this;
  12131. ctor.Flags |= MethodFlags.Public;
  12132. int n = this.Rank;
  12133. ctor.Parameters = new ParameterList(n);
  12134. for (int i = 0; i < n; i++){
  12135. Parameter par = new Parameter();
  12136. par.DeclaringMethod = ctor;
  12137. par.Type = CoreSystemTypes.Int32;
  12138. ctor.Parameters.Add(par);
  12139. }
  12140. this.ctorList = new MemberList(2);
  12141. this.ctorList.Add(ctor);
  12142. ctor = new InstanceInitializer();
  12143. ctor.DeclaringType = this;
  12144. ctor.Flags |= MethodFlags.Public;
  12145. ctor.Parameters = new ParameterList(n=n*2);
  12146. for (int i = 0; i < n; i++){
  12147. Parameter par = new Parameter();
  12148. par.Type = CoreSystemTypes.Int32;
  12149. par.DeclaringMethod = ctor;
  12150. ctor.Parameters.Add(par);
  12151. }
  12152. this.ctorList.Add(ctor);
  12153. }
  12154. }
  12155. }
  12156. return (Method)this.ctorList[0];
  12157. }
  12158. }
  12159. public Method Getter{
  12160. get{
  12161. if (this.getterList == null){
  12162. lock(this){
  12163. if (this.getterList == null){
  12164. Method getter = new Method();
  12165. getter.Name = StandardIds.Get;
  12166. getter.DeclaringType = this;
  12167. getter.CallingConvention = CallingConventionFlags.HasThis;
  12168. getter.Flags = MethodFlags.Public;
  12169. getter.Parameters = new ParameterList();
  12170. for (int i = 0, n = this.Rank; i < n; i++){
  12171. Parameter par = new Parameter();
  12172. par.Type = CoreSystemTypes.Int32;
  12173. par.DeclaringMethod = getter;
  12174. getter.Parameters.Add(par);
  12175. }
  12176. getter.ReturnType = this.ElementType;
  12177. this.getterList = new MemberList();
  12178. this.getterList.Add(getter);
  12179. }
  12180. }
  12181. }
  12182. return (Method)this.getterList[0];
  12183. }
  12184. }
  12185. public Method Setter{
  12186. get{
  12187. if (this.setterList == null){
  12188. lock(this){
  12189. if (this.setterList == null){
  12190. Method setter = new Method();
  12191. setter.Name = StandardIds.Set;
  12192. setter.DeclaringType = this;
  12193. setter.CallingConvention = CallingConventionFlags.HasThis;
  12194. setter.Flags = MethodFlags.Public;
  12195. setter.Parameters = new ParameterList();
  12196. Parameter par;
  12197. for (int i = 0, n = this.Rank; i < n; i++){
  12198. par = new Parameter();
  12199. par.Type = CoreSystemTypes.Int32;
  12200. par.DeclaringMethod = setter;
  12201. setter.Parameters.Add(par);
  12202. }
  12203. par = new Parameter();
  12204. par.Type = this.ElementType;
  12205. par.DeclaringMethod = setter;
  12206. setter.Parameters.Add(par);
  12207. setter.ReturnType = CoreSystemTypes.Void;
  12208. this.setterList = new MemberList();
  12209. this.setterList.Add(setter);
  12210. }
  12211. }
  12212. }
  12213. return (Method)this.setterList[0];
  12214. }
  12215. }
  12216. public Method Address{
  12217. get{
  12218. if (this.addressList == null){
  12219. lock(this){
  12220. if (this.addressList == null){
  12221. Method address = new Method();
  12222. address.Name = StandardIds.Address;
  12223. address.DeclaringType = this;
  12224. address.CallingConvention = CallingConventionFlags.HasThis;
  12225. address.Flags = MethodFlags.Public;
  12226. address.Parameters = new ParameterList();
  12227. for (int i = 0, n = this.Rank; i < n; i++){
  12228. Parameter par = new Parameter();
  12229. par.Type = CoreSystemTypes.Int32;
  12230. par.DeclaringMethod = address;
  12231. address.Parameters.Add(par);
  12232. }
  12233. address.ReturnType = this.ElementType.GetReferenceType();
  12234. this.addressList = new MemberList();
  12235. this.addressList.Add(address);
  12236. }
  12237. }
  12238. }
  12239. return (Method)this.addressList[0];
  12240. }
  12241. }
  12242. public override bool IsAssignableTo(TypeNode targetType){
  12243. if (targetType == null) return false;
  12244. if (targetType == this || targetType == CoreSystemTypes.Object || targetType == CoreSystemTypes.Array || targetType == SystemTypes.ICloneable) return true;
  12245. if (CoreSystemTypes.Array.IsAssignableTo(targetType)) return true;
  12246. if (targetType.Template != null && SystemTypes.GenericIEnumerable != null && SystemTypes.GenericIEnumerable.DeclaringModule == CoreSystemTypes.SystemAssembly) {
  12247. if (targetType.Template == SystemTypes.GenericIEnumerable || targetType.Template == SystemTypes.GenericICollection ||
  12248. targetType.Template == SystemTypes.GenericIList) {
  12249. if (targetType.TemplateArguments == null || targetType.TemplateArguments.Count != 1) {
  12250. Debug.Assert(false); return false;
  12251. }
  12252. TypeNode ienumElementType = targetType.TemplateArguments[0];
  12253. if (this.ElementType == ienumElementType) return true;
  12254. if (this.ElementType.IsValueType) return false;
  12255. return this.ElementType.IsAssignableTo(ienumElementType);
  12256. }
  12257. }
  12258. ArrayType targetArrayType = targetType as ArrayType;
  12259. if (targetArrayType == null) return false;
  12260. if (this.Rank != 1 || targetArrayType.Rank != 1) return false;
  12261. TypeNode thisElementType = this.ElementType;
  12262. if (thisElementType == null) return false;
  12263. #if ExtendedRuntime
  12264. thisElementType = TypeNode.StripModifier(thisElementType, ExtendedRuntimeTypes.NonNullType);
  12265. // DelayedAttribute is used as a modifier on some array allocation types to mark it as
  12266. // an explictly delayed allocation.
  12267. thisElementType = TypeNode.StripModifier(thisElementType, ExtendedRuntimeTypes.DelayedAttribute);
  12268. #endif
  12269. if (thisElementType == targetArrayType.ElementType) return true;
  12270. if (thisElementType.IsValueType) return false;
  12271. return thisElementType.IsAssignableTo(targetArrayType.ElementType);
  12272. }
  12273. public override bool IsStructural{
  12274. get{return true;}
  12275. }
  12276. protected TypeNodeList structuralElementTypes;
  12277. public override TypeNodeList StructuralElementTypes{
  12278. get{
  12279. TypeNodeList result = this.structuralElementTypes;
  12280. if (result != null) return result;
  12281. this.structuralElementTypes = result = new TypeNodeList(1);
  12282. result.Add(this.ElementType);
  12283. return result;
  12284. }
  12285. }
  12286. public override bool IsStructurallyEquivalentTo(TypeNode type){
  12287. if (type == null) return false;
  12288. if (this == type) return true;
  12289. ArrayType t = type as ArrayType;
  12290. if (t == null) return false;
  12291. if (this.Rank != t.Rank) return false;
  12292. if (this.ElementType == null || t.ElementType == null) return false;
  12293. if (this.ElementType != t.ElementType && !this.ElementType.IsStructurallyEquivalentTo(t.ElementType)) return false;
  12294. if (th