PageRenderTime 137ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 3ms

/SHFB/Source/MRefBuilder/CCI/Nodes.cs

#
C# | 12670 lines | 11248 code | 573 blank | 849 comment | 3031 complexity | 0ba47bd13f8400a94c762348c4ab196d MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. // Copyright Š Microsoft Corporation.
  2. // This source file is subject to the Microsoft Permissive License.
  3. // See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.
  4. // All other rights reserved.
  5. // Change history:
  6. // 02/03/2012 - EFW - Fixed Method.ImplicitlyImplementedInterfaceMethods so that it recognizes interface
  7. // member matches when the return type is generic.
  8. // 03/28/2012 - EFW - Fixed TypeNode.Attributes so that it won't get stuck in an endless loop if a type's
  9. // attribute references the type being parsed.
  10. // 04/04/2012 - EFW - Fixed TypeNode.NestedTypes so that it won't get stuck in an endless loop when a type
  11. // contains a nested type that itself implements a nested type from within the containing type.
  12. // 11/30/2012 - EFW - Added updates based on changes submitted by ComponentOne to fix crashes caused by
  13. // obfuscated member names.
  14. // 11/21/2013 - EFW - Cleared out the conditional statements and unused code and updated based on changes to
  15. // ListTemplate.cs.
  16. // 03/14/2014 - EFW - Fixed bug in TypeNode.GetMatchingMethod() reported by SHarwell.
  17. using System.Collections;
  18. using System.Collections.Generic;
  19. using System.Globalization;
  20. using System.Compiler.Metadata;
  21. using System.Diagnostics;
  22. using System.IO;
  23. using System.Text;
  24. using System.Xml;
  25. using BindingFlags = System.Reflection.BindingFlags;
  26. namespace System.Compiler
  27. {
  28. /// <summary>
  29. /// This interface can be used to link an arbitrary source text provider into an IR tree via a DocumentText instance.
  30. /// </summary>
  31. public interface ISourceText
  32. {
  33. /// <summary>
  34. /// The number of characters in the source text.
  35. /// A "character" corresponds to a System.Char which is actually a Unicode UTF16 code point to be precise.
  36. /// </summary>
  37. int Length { get; }
  38. /// <summary>
  39. /// Retrieves a substring from this instance. The substring starts with the character at the specified index and has a specified length.
  40. /// </summary>
  41. string Substring(int startIndex, int length);
  42. /// <summary>
  43. /// Retrieves the character at the given position. The first character is at position zero.
  44. /// </summary>
  45. char this[int position] { get; }
  46. /// <summary>
  47. /// Indicates that the text has been fully scanned and further references to the text are expected to be infrequent.
  48. /// The underlying object can now choose to clear cached information if it comes under resource pressure.
  49. /// </summary>
  50. void MakeCollectible();
  51. }
  52. public unsafe interface ISourceTextBuffer : ISourceText
  53. {
  54. /// <summary>
  55. /// Returns null unless the implementer is based on an ASCII buffer that stays alive as long at the implementer itself.
  56. /// An implementer that returns a non-null value is merely a wrapper to keep the buffer alive. No further methods will
  57. /// be called on the interface in this case.
  58. /// </summary>
  59. byte* Buffer { get; }
  60. }
  61. /// <summary>
  62. /// This class provides a uniform interface to program sources provided in the form of Unicode strings,
  63. /// unsafe pointers to ASCII buffers (as obtained from a memory mapped file, for instance) as well as
  64. /// arbitrary source text providers that implement the ISourceText interface.
  65. /// </summary>
  66. public sealed unsafe class DocumentText
  67. {
  68. /// <summary>
  69. /// If this is not null it is used to obtain 8-bit ASCII characters.
  70. /// </summary>
  71. public byte* AsciiStringPtr;
  72. /// <summary>
  73. /// If this is not null it represents a Unicode string encoded as UTF16.
  74. /// </summary>
  75. public string Source;
  76. /// <summary>
  77. /// If this is not null the object implement ISourceText provides some way to get at individual characters and substrings.
  78. /// </summary>
  79. public ISourceText TextProvider;
  80. /// <summary>
  81. /// The number of characters in the source document.
  82. /// A "character" corresponds to a System.Char which is actually a Unicode UTF16 code point to be precise.
  83. /// </summary>
  84. public int Length;
  85. public DocumentText(string source)
  86. {
  87. if(source == null) { Debug.Assert(false); return; }
  88. this.Source = source;
  89. this.Length = source.Length;
  90. }
  91. public DocumentText(ISourceText textProvider)
  92. {
  93. if(textProvider == null) { Debug.Assert(false); return; }
  94. this.TextProvider = textProvider;
  95. this.Length = textProvider.Length;
  96. }
  97. public unsafe DocumentText(ISourceTextBuffer textProvider)
  98. {
  99. if(textProvider == null) { Debug.Assert(false); return; }
  100. this.TextProvider = textProvider;
  101. this.AsciiStringPtr = textProvider.Buffer;
  102. this.Length = textProvider.Length;
  103. }
  104. /// <summary>
  105. /// Compare this.Substring(offset, length) for equality with str.
  106. /// Call this only if str.Length is known to be equal to length.
  107. /// </summary>
  108. public bool Equals(string str, int position, int length)
  109. { //TODO: (int position, int length, string str)
  110. if(str == null) { Debug.Assert(false); return false; }
  111. if(str.Length != length) { Debug.Assert(false); return false; }
  112. if(position < 0 || position + length > this.Length) { Debug.Assert(false); return false; }
  113. unsafe
  114. {
  115. byte* p = this.AsciiStringPtr;
  116. if(p != null)
  117. {
  118. for(int i = position, j = 0; j < length; i++, j++)
  119. if(((char)*(p + i)) != str[j])
  120. return false;
  121. return true;
  122. }
  123. }
  124. string source = this.Source;
  125. if(source != null)
  126. {
  127. for(int i = position, j = 0; j < length; i++, j++)
  128. if(source[i] != str[j])
  129. return false;
  130. return true;
  131. }
  132. ISourceText myProvider = this.TextProvider;
  133. if(myProvider == null) { Debug.Assert(false); return false; }
  134. for(int i = position, j = 0; j < length; i++, j++)
  135. if(myProvider[i] != str[j])
  136. return false;
  137. return true;
  138. }
  139. /// <summary>
  140. /// Compares the substring of the specified length starting at offset, with the substring in DocumentText starting at textOffset.
  141. /// </summary>
  142. /// <param name="offset">The index of the first character of the substring of this DocumentText.</param>
  143. /// <param name="text">The Document text with the substring being compared to.</param>
  144. /// <param name="textOffset">The index of the first character of the substring of the DocumentText being compared to.</param>
  145. /// <param name="length">The number of characters in the substring being compared.</param>
  146. /// <returns></returns>
  147. public bool Equals(int offset, DocumentText text, int textOffset, int length)
  148. { //TODO: (int position, int length, DocumentText text, int textPosition)
  149. if(offset < 0 || length < 0 || offset + length > this.Length) { Debug.Assert(false); return false; }
  150. if(textOffset < 0 || text == null || textOffset + length > text.Length) { Debug.Assert(false); return false; }
  151. unsafe
  152. {
  153. byte* p = this.AsciiStringPtr;
  154. if(p != null)
  155. {
  156. unsafe
  157. {
  158. byte* q = text.AsciiStringPtr;
  159. if(q != null)
  160. {
  161. for(int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
  162. if(*(p + i) != *(q + j))
  163. return false;
  164. return true;
  165. }
  166. }
  167. string textSource = text.Source;
  168. if(textSource != null)
  169. {
  170. for(int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
  171. if(((char)*(p + i)) != textSource[j])
  172. return false;
  173. return true;
  174. }
  175. ISourceText textProvider = text.TextProvider;
  176. if(textProvider == null) { Debug.Assert(false); return false; }
  177. for(int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
  178. if(((char)*(p + i)) != textProvider[j])
  179. return false;
  180. return true;
  181. }
  182. }
  183. string source = this.Source;
  184. if(source != null)
  185. {
  186. unsafe
  187. {
  188. byte* q = text.AsciiStringPtr;
  189. if(q != null)
  190. {
  191. for(int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
  192. if(source[i] != (char)*(q + j))
  193. return false;
  194. return true;
  195. }
  196. }
  197. string textSource = text.Source;
  198. if(textSource != null)
  199. {
  200. for(int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
  201. if(source[i] != textSource[j])
  202. return false;
  203. return true;
  204. }
  205. ISourceText textProvider = text.TextProvider;
  206. if(textProvider == null) { Debug.Assert(false); return false; }
  207. for(int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
  208. if(source[i] != textProvider[j])
  209. return false;
  210. return true;
  211. }
  212. {
  213. ISourceText myProvider = this.TextProvider;
  214. if(myProvider == null) { Debug.Assert(false); return false; }
  215. unsafe
  216. {
  217. byte* q = text.AsciiStringPtr;
  218. if(q != null)
  219. {
  220. for(int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
  221. if(myProvider[i] != (char)*(q + j))
  222. return false;
  223. return true;
  224. }
  225. }
  226. string textSource = text.Source;
  227. if(textSource != null)
  228. {
  229. for(int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
  230. if(myProvider[i] != textSource[j])
  231. return false;
  232. return true;
  233. }
  234. ISourceText textProvider = text.TextProvider;
  235. if(textProvider == null) { Debug.Assert(false); return false; }
  236. for(int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
  237. if(myProvider[i] != textProvider[j])
  238. return false;
  239. return true;
  240. }
  241. }
  242. /// <summary>
  243. /// Retrieves a substring from this instance. The substring starts at a specified character position and has a specified length.
  244. /// </summary>
  245. public string/*!*/ Substring(int position, int length)
  246. {
  247. if(position < 0 || length < 0 || position + length > this.Length + 1) { Debug.Assert(false); return ""; }
  248. if(position + length > this.Length)
  249. length = this.Length - position; //Allow virtual EOF character to be included in length
  250. if(this.AsciiStringPtr != null)
  251. {
  252. unsafe
  253. {
  254. return new String((sbyte*)this.AsciiStringPtr, position, length, System.Text.Encoding.ASCII);
  255. }
  256. }
  257. else if(this.Source != null)
  258. return this.Source.Substring(position, length);
  259. else if(this.TextProvider != null)
  260. return this.TextProvider.Substring(position, length);
  261. else
  262. {
  263. Debug.Assert(false);
  264. return "";
  265. }
  266. }
  267. /// <summary>
  268. /// Retrieves the character at the given position. The first character is at position zero.
  269. /// </summary>
  270. public char this[int position]
  271. {
  272. get
  273. {
  274. if(position < 0 || position >= this.Length) { Debug.Assert(false); return (char)0; }
  275. if(this.AsciiStringPtr != null)
  276. {
  277. unsafe
  278. {
  279. unchecked
  280. {
  281. return (char)*(this.AsciiStringPtr + position);
  282. }
  283. }
  284. }
  285. else if(this.Source != null)
  286. return this.Source[position];
  287. else if(this.TextProvider != null)
  288. return this.TextProvider[position];
  289. else
  290. {
  291. Debug.Assert(false);
  292. return (char)0;
  293. }
  294. }
  295. }
  296. }
  297. /// <summary>
  298. /// A source document from which an Abstract Syntax Tree has been derived.
  299. /// </summary>
  300. public class Document
  301. {
  302. /// <summary>
  303. /// A Guid that identifies the kind of document to applications such as a debugger. Typically System.Diagnostics.SymbolStore.SymDocumentType.Text.
  304. /// </summary>
  305. public System.Guid DocumentType;
  306. /// <summary>
  307. /// A Guid that identifies the programming language used in the source document. Typically used by a debugger to locate language specific logic.
  308. /// </summary>
  309. public System.Guid Language;
  310. /// <summary>
  311. /// A Guid that identifies the compiler vendor programming language used in the source document. Typically used by a debugger to locate vendor specific logic.
  312. /// </summary>
  313. public System.Guid LanguageVendor;
  314. /// <summary>
  315. /// The line number corresponding to the first character in Text. Typically 1 but can be changed by C# preprocessor directives.
  316. /// </summary>
  317. public int LineNumber;
  318. /// <summary>
  319. /// Indicates that the document contains machine generated source code that should not show up in tools such as debuggers.
  320. /// Can be set by C# preprocessor directives.
  321. /// </summary>
  322. public bool Hidden;
  323. /// <summary>
  324. /// 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.
  325. /// </summary>
  326. public string/*!*/ Name;
  327. /// <summary>
  328. /// Contains the source text.
  329. /// </summary>
  330. public DocumentText Text;
  331. public Document()
  332. {
  333. this.Name = "";
  334. //^ base();
  335. }
  336. public Document(string/*!*/ name, int lineNumber, string text, System.Guid documentType, System.Guid language, System.Guid languageVendor)
  337. : this(name, lineNumber, new DocumentText(text), documentType, language, languageVendor)
  338. {
  339. }
  340. public Document(string/*!*/ name, int lineNumber, DocumentText text, System.Guid documentType, System.Guid language, System.Guid languageVendor)
  341. {
  342. this.DocumentType = documentType;
  343. this.Language = language;
  344. this.LanguageVendor = languageVendor;
  345. this.LineNumber = lineNumber;
  346. this.Name = name;
  347. this.Text = text;
  348. //^ base();
  349. }
  350. /// <summary>
  351. /// Maps the given zero based character position to the number of the source line containing the same character.
  352. /// Line number counting starts from the value of LineNumber.
  353. /// </summary>
  354. public virtual int GetLine(int position)
  355. {
  356. int line = 0;
  357. int column = 0;
  358. this.GetPosition(position, out line, out column);
  359. return line + this.LineNumber;
  360. }
  361. /// <summary>
  362. /// Maps the given zero based character position in the entire text to the position of the same character in a source line.
  363. /// Counting within the source line starts at 1.
  364. /// </summary>
  365. public virtual int GetColumn(int position)
  366. {
  367. int line = 0;
  368. int column = 0;
  369. this.GetPosition(position, out line, out column);
  370. return column + 1;
  371. }
  372. /// <summary>
  373. /// Given a startLine, startColum, endLine and endColumn, this returns the corresponding startPos and endPos. In other words it
  374. /// converts a range expression in line and columns to a range expressed as a start and end character position.
  375. /// </summary>
  376. /// <param name="startLine">The number of the line containing the first character. The number of the first line equals this.LineNumber.</param>
  377. /// <param name="startColumn">The position of the first character relative to the start of the line. Counting from 1.</param>
  378. /// <param name="endLine">The number of the line contain the character that immediate follows the last character of the range.</param>
  379. /// <param name="endColumn">The position, in the last line, of the character that immediately follows the last character of the range.</param>
  380. /// <param name="startPos">The position in the entire text of the first character of the range, counting from 0.</param>
  381. /// <param name="endPos">The position in the entire text of the character following the last character of the range.</param>
  382. public virtual void GetOffsets(int startLine, int startColumn, int endLine, int endColumn, out int startPos, out int endPos)
  383. {
  384. lock(this)
  385. {
  386. if(this.lineOffsets == null)
  387. this.ComputeLineOffsets();
  388. //^ assert this.lineOffsets != null;
  389. startPos = this.lineOffsets[startLine - this.LineNumber] + startColumn - 1;
  390. endPos = this.lineOffsets[endLine - this.LineNumber] + endColumn - 1;
  391. }
  392. }
  393. /// <summary>
  394. /// Retrieves a substring from the text of this Document. The substring starts at a specified character position and has a specified length.
  395. /// </summary>
  396. public virtual string Substring(int position, int length)
  397. {
  398. if(this.Text == null)
  399. return null;
  400. return this.Text.Substring(position, length);
  401. }
  402. /// <summary>
  403. /// Counts the number of end of line marker sequences in the given text.
  404. /// </summary>
  405. protected int GetLineCount(string/*!*/ text)
  406. {
  407. int n = text == null ? 0 : text.Length;
  408. int count = 0;
  409. for(int i = 0; i < n; i++)
  410. {
  411. switch(text[i])
  412. {
  413. case '\r':
  414. if(i + 1 < n && text[i + 1] == '\n')
  415. i++;
  416. count++;
  417. break;
  418. case '\n':
  419. case (char)0x2028:
  420. case (char)0x2029:
  421. count++;
  422. break;
  423. }
  424. }
  425. return count;
  426. }
  427. /// <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>
  428. private int[] lineOffsets;
  429. /// <summary>The number of lines in Text.</summary>
  430. private int lines;
  431. /// <summary>
  432. /// Returns the index in this.lineOffsets array such that this.lineOffsets[index] is less than or equal to offset
  433. /// and offset is less than lineOffsets[index+1]
  434. /// </summary>
  435. private int Search(int offset)
  436. {
  437. tryAgain:
  438. int[] lineOffsets = this.lineOffsets;
  439. int lines = this.lines;
  440. if(lineOffsets == null) { Debug.Assert(false); return -1; }
  441. if(offset < 0) { Debug.Assert(false); return -1; }
  442. int mid = 0;
  443. int low = 0;
  444. int high = lines - 1;
  445. while(low < high)
  446. {
  447. mid = (low + high) / 2;
  448. if(lineOffsets[mid] <= offset)
  449. {
  450. if(offset < lineOffsets[mid + 1])
  451. return mid;
  452. else
  453. low = mid + 1;
  454. }
  455. else
  456. high = mid;
  457. }
  458. Debug.Assert(lines == this.lines);
  459. Debug.Assert(lineOffsets[low] <= offset);
  460. Debug.Assert(offset < lineOffsets[low + 1]);
  461. if(lineOffsets != this.lineOffsets)
  462. goto tryAgain;
  463. return low;
  464. }
  465. /// <summary>
  466. /// Maps the given zero based character position in the entire text to a (line, column) pair corresponding to the same position.
  467. /// Counting within the source line starts at 0. Counting source lines start at 0.
  468. /// </summary>
  469. private void GetPosition(int offset, out int line, out int column)
  470. {
  471. line = 0;
  472. column = 0;
  473. if(offset < 0 || this.Text == null || offset > this.Text.Length) { Debug.Assert(false); return; }
  474. lock(this)
  475. {
  476. if(this.lineOffsets == null)
  477. this.ComputeLineOffsets();
  478. if(this.lineOffsets == null) { Debug.Assert(false); return; }
  479. int[] lineOffsets = this.lineOffsets;
  480. int index = this.Search(offset);
  481. Debug.Assert(lineOffsets == this.lineOffsets);
  482. if(index < 0 || index >= this.lineOffsets.Length) { Debug.Assert(false); return; }
  483. Debug.Assert(this.lineOffsets[index] <= offset && offset < this.lineOffsets[index + 1]);
  484. line = index;
  485. column = offset - this.lineOffsets[index];
  486. }
  487. }
  488. /// <summary>
  489. /// Adds the given offset to the this.lineOffsets table as the offset corresponding to the start of line this.lines+1.
  490. /// </summary>
  491. private void AddOffset(int offset)
  492. {
  493. if(this.lineOffsets == null || this.lines < 0) { Debug.Assert(false); return; }
  494. if(this.lines >= this.lineOffsets.Length)
  495. {
  496. int n = this.lineOffsets.Length;
  497. if(n <= 0)
  498. n = 16;
  499. int[] newLineOffsets = new int[n * 2];
  500. Array.Copy(this.lineOffsets, newLineOffsets, this.lineOffsets.Length);
  501. this.lineOffsets = newLineOffsets;
  502. }
  503. this.lineOffsets[this.lines++] = offset;
  504. }
  505. public virtual void InsertOrDeleteLines(int offset, int lineCount)
  506. {
  507. if(lineCount == 0)
  508. return;
  509. if(offset < 0 || this.Text == null || offset > this.Text.Length) { Debug.Assert(false); return; }
  510. lock(this)
  511. {
  512. if(this.lineOffsets == null)
  513. if(this.lineOffsets == null)
  514. this.ComputeLineOffsets();
  515. if(lineCount < 0)
  516. this.DeleteLines(offset, -lineCount);
  517. else
  518. this.InsertLines(offset, lineCount);
  519. }
  520. }
  521. private void DeleteLines(int offset, int lineCount)
  522. //^ requires offset >= 0 && this.Text != null && offset < this.Text.Length && lineCount > 0 && this.lineOffsets != null;
  523. {
  524. Debug.Assert(offset >= 0 && this.Text != null && offset < this.Text.Length && lineCount > 0 && this.lineOffsets != null);
  525. int index = this.Search(offset);
  526. if(index < 0 || index >= this.lines) { Debug.Assert(false); return; }
  527. for(int i = index + 1; i + lineCount < this.lines; i++)
  528. {
  529. this.lineOffsets[i] = this.lineOffsets[i + lineCount];
  530. }
  531. this.lines -= lineCount;
  532. if(this.lines <= index) { Debug.Assert(false); this.lines = index + 1; }
  533. }
  534. private void InsertLines(int offset, int lineCount)
  535. //^ requires offset >= 0 && this.Text != null && offset < this.Text.Length && lineCount > 0 && this.lineOffsets != null;
  536. {
  537. Debug.Assert(offset >= 0 && this.Text != null && offset < this.Text.Length && lineCount > 0 && this.lineOffsets != null);
  538. int index = this.Search(offset);
  539. if(index < 0 || index >= this.lines) { Debug.Assert(false); return; }
  540. int n = this.lineOffsets[this.lines - 1];
  541. for(int i = 0; i < lineCount; i++)
  542. this.AddOffset(++n);
  543. for(int i = lineCount; i > 0; i--)
  544. {
  545. this.lineOffsets[index + i + 1] = this.lineOffsets[index + 1];
  546. }
  547. }
  548. /// <summary>
  549. /// Populates this.lineOffsets with an array of offsets, with offset at index i corresponding to the position of the first
  550. /// character of line i, (counting lines from 0).
  551. /// </summary>
  552. private void ComputeLineOffsets()
  553. //ensures this.lineOffsets != null;
  554. {
  555. if(this.Text == null) { Debug.Assert(false); return; }
  556. int n = this.Text.Length;
  557. this.lineOffsets = new int[n / 10 + 1];
  558. this.lines = 0;
  559. this.AddOffset(0);
  560. for(int i = 0; i < n; i++)
  561. {
  562. switch(this.Text[i])
  563. {
  564. case '\r':
  565. if(i + 1 < n && this.Text[i + 1] == '\n')
  566. i++;
  567. this.AddOffset(i + 1);
  568. break;
  569. case '\n':
  570. case (char)0x2028:
  571. case (char)0x2029:
  572. this.AddOffset(i + 1);
  573. break;
  574. }
  575. }
  576. this.AddOffset(n + 1);
  577. this.AddOffset(n + 2);
  578. }
  579. /// <summary> Add one to this every time a Document instance gets a unique key.</summary>
  580. private static int uniqueKeyCounter;
  581. private int uniqueKey;
  582. /// <summary>
  583. /// An integer that uniquely distinguishes this document instance from every other document instance.
  584. /// This provides an efficient equality test to facilitate hashing.
  585. /// </summary>
  586. public int UniqueKey
  587. {
  588. get
  589. {
  590. if(this.uniqueKey == 0)
  591. {
  592. TryAgain:
  593. int c = Document.uniqueKeyCounter;
  594. int cp1 = c == int.MaxValue ? 1 : c + 1;
  595. if(System.Threading.Interlocked.CompareExchange(ref Document.uniqueKeyCounter, cp1, c) != c)
  596. goto TryAgain;
  597. this.uniqueKey = cp1;
  598. }
  599. return this.uniqueKey;
  600. }
  601. }
  602. }
  603. internal class UnmanagedDocument : Document
  604. {
  605. internal UnmanagedDocument(IntPtr ptrToISymUnmanagedDocument)
  606. {
  607. //^ base();
  608. ISymUnmanagedDocument idoc =
  609. (ISymUnmanagedDocument)System.Runtime.InteropServices.Marshal.GetTypedObjectForIUnknown(ptrToISymUnmanagedDocument, typeof(ISymUnmanagedDocument));
  610. if(idoc != null)
  611. {
  612. try
  613. {
  614. idoc.GetDocumentType(out this.DocumentType);
  615. idoc.GetLanguage(out this.Language);
  616. idoc.GetLanguageVendor(out this.LanguageVendor);
  617. uint capacity = 1024;
  618. uint len = 0;
  619. char[] buffer = new char[capacity];
  620. while(capacity >= 1024)
  621. {
  622. idoc.GetURL(capacity, out len, buffer);
  623. if(len < capacity)
  624. break;
  625. capacity += 1024;
  626. buffer = new char[capacity];
  627. }
  628. if(len > 0)
  629. this.Name = new String(buffer, 0, (int)len - 1);
  630. }
  631. finally
  632. {
  633. System.Runtime.InteropServices.Marshal.ReleaseComObject(idoc);
  634. }
  635. }
  636. this.LineNumber = -1;
  637. this.Text = null;
  638. }
  639. private List<int> lineList = new List<int>();
  640. private List<int> columnList = new List<int>();
  641. public override int GetLine(int offset)
  642. {
  643. return this.lineList[offset];
  644. }
  645. public override int GetColumn(int offset)
  646. {
  647. return this.columnList[offset];
  648. }
  649. public override void GetOffsets(int startLine, int startColumn, int endLine, int endColumn, out int startCol, out int endCol)
  650. {
  651. int i = UnmanagedDocument.BinarySearch(this.lineList, startLine);
  652. List<int> columnList = this.columnList;
  653. startCol = 0;
  654. for(int j = i, n = columnList.Count; j < n; j++)
  655. {
  656. if(columnList[j] >= startColumn) { startCol = j; break; }
  657. }
  658. endCol = 0;
  659. i = UnmanagedDocument.BinarySearch(this.lineList, endLine);
  660. for(int j = i, n = columnList.Count; j < n; j++)
  661. {
  662. if(columnList[j] >= endColumn) { endCol = j; break; }
  663. }
  664. }
  665. private static int BinarySearch(List<int> list, int value)
  666. {
  667. int mid = 0;
  668. int low = 0;
  669. int high = list.Count - 1;
  670. while(low < high)
  671. {
  672. mid = low + (high - low) / 2;
  673. if(list[mid] <= value)
  674. {
  675. if(list[mid + 1] > value)
  676. return mid;
  677. else
  678. low = mid + 1;
  679. }
  680. else
  681. high = mid;
  682. }
  683. return low;
  684. }
  685. public override void InsertOrDeleteLines(int offset, int lineCount)
  686. {
  687. Debug.Assert(false); //Caller should not be modifying an unmanaged document
  688. }
  689. internal int GetOffset(uint line, uint column)
  690. {
  691. this.lineList.Add((int)line);
  692. this.columnList.Add((int)column);
  693. return this.lineList.Count - 1;
  694. }
  695. }
  696. /// <summary>
  697. /// Records a location within a source document that corresponds to an Abstract Syntax Tree node.
  698. /// </summary>
  699. public struct SourceContext
  700. {
  701. /// <summary>The source document within which the AST node is located. Null if the node is not derived from a source document.</summary>
  702. public Document Document;
  703. /// <summary>
  704. /// The zero based index of the first character beyond the last character in the source document that corresponds to the AST node.
  705. /// </summary>
  706. public int EndPos;
  707. /// <summary>
  708. /// The zero based index of the first character in the source document that corresponds to the AST node.
  709. /// </summary>
  710. public int StartPos;
  711. public SourceContext(Document document)
  712. : this(document, 0, document == null ? 0 : (document.Text == null ? 0 : document.Text.Length))
  713. {
  714. }
  715. public SourceContext(Document document, int startPos, int endPos)
  716. {
  717. this.Document = document;
  718. this.StartPos = startPos;
  719. this.EndPos = endPos;
  720. }
  721. public SourceContext(Document/*!*/ document,
  722. int startLine, int startColumn, int endLine, int endColumn)
  723. {
  724. this.Document = document;
  725. this.Document.GetOffsets(startLine, startColumn, endLine, endColumn, out this.StartPos, out this.EndPos);
  726. }
  727. /// <summary>
  728. /// The number (counting from Document.LineNumber) of the line containing the first character in the source document that corresponds to the AST node.
  729. /// </summary>
  730. public int StartLine
  731. {
  732. get
  733. {
  734. if(this.Document == null)
  735. return 0;
  736. return this.Document.GetLine(this.StartPos);
  737. }
  738. }
  739. /// <summary>
  740. /// The number (counting from one) of the line column containing the first character in the source document that corresponds to the AST node.
  741. /// </summary>
  742. public int StartColumn
  743. {
  744. get
  745. {
  746. if(this.Document == null)
  747. return 0;
  748. return this.Document.GetColumn(this.StartPos);
  749. }
  750. }
  751. /// <summary>
  752. /// 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.
  753. /// </summary>
  754. public int EndLine
  755. {
  756. get
  757. {
  758. if(this.Document == null || (this.Document.Text == null && !(this.Document is UnmanagedDocument)))
  759. return 0;
  760. if(this.Document.Text != null && this.EndPos >= this.Document.Text.Length)
  761. this.EndPos = this.Document.Text.Length;
  762. return this.Document.GetLine(this.EndPos);
  763. }
  764. }
  765. /// <summary>
  766. /// 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.
  767. /// </summary>
  768. public int EndColumn
  769. {
  770. get
  771. {
  772. if(this.Document == null || (this.Document.Text == null && !(this.Document is UnmanagedDocument)))
  773. return 0;
  774. if(this.Document.Text != null && this.EndPos >= this.Document.Text.Length)
  775. this.EndPos = this.Document.Text.Length;
  776. return this.Document.GetColumn(this.EndPos);
  777. }
  778. }
  779. /// <summary>
  780. /// Returns true if the line and column is greater than or equal the position of the first character
  781. /// and less than or equal to the position of the last character
  782. /// of the source document that corresponds to the AST node.
  783. /// </summary>
  784. /// <param name="line">A line number(counting from Document.LineNumber)</param>
  785. /// <param name="column">A column number (counting from one)</param>
  786. /// <returns></returns>
  787. public bool Encloses(int line, int column)
  788. {
  789. if(line < this.StartLine || line > this.EndLine)
  790. return false;
  791. if(line == this.StartLine)
  792. return column >= this.StartColumn && (column <= this.EndColumn || line < this.EndLine);
  793. if(line == this.EndLine)
  794. return column <= this.EndColumn;
  795. return true;
  796. }
  797. public bool Encloses(SourceContext sourceContext)
  798. {
  799. return this.StartPos <= sourceContext.StartPos && this.EndPos >= sourceContext.EndPos && this.EndPos > sourceContext.StartPos;
  800. }
  801. /// <summary>
  802. /// The substring of the source document that corresponds to the AST node.
  803. /// </summary>
  804. public string SourceText
  805. {
  806. get
  807. {
  808. if(this.Document == null)
  809. return null;
  810. return this.Document.Substring(this.StartPos, this.EndPos - this.StartPos);
  811. }
  812. }
  813. }
  814. public sealed class MarshallingInformation
  815. {
  816. private string @class;
  817. private string cookie;
  818. private int elementSize;
  819. private NativeType elementType;
  820. private NativeType nativeType;
  821. private int numberOfElements;
  822. private int paramIndex;
  823. private int size;
  824. public MarshallingInformation Clone()
  825. {
  826. return (MarshallingInformation)base.MemberwiseClone();
  827. }
  828. public string Class
  829. {
  830. get { return this.@class; }
  831. set { this.@class = value; }
  832. }
  833. public string Cookie
  834. {
  835. get { return this.cookie; }
  836. set { this.cookie = value; }
  837. }
  838. public int ElementSize
  839. {
  840. get { return this.elementSize; }
  841. set { this.elementSize = value; }
  842. }
  843. public NativeType ElementType
  844. {
  845. get { return this.elementType; }
  846. set { this.elementType = value; }
  847. }
  848. public NativeType NativeType
  849. {
  850. get { return this.nativeType; }
  851. set { this.nativeType = value; }
  852. }
  853. public int NumberOfElements
  854. {
  855. get { return this.numberOfElements; }
  856. set { this.numberOfElements = value; }
  857. }
  858. public int ParamIndex
  859. {
  860. get { return this.paramIndex; }
  861. set { this.paramIndex = value; }
  862. }
  863. public int Size
  864. {
  865. get { return this.size; }
  866. set { this.size = value; }
  867. }
  868. }
  869. public enum NativeType
  870. {
  871. Bool = 0x2, // 4 byte boolean value (true != 0, false == 0)
  872. I1 = 0x3, // 1 byte signed value
  873. U1 = 0x4, // 1 byte unsigned value
  874. I2 = 0x5, // 2 byte signed value
  875. U2 = 0x6, // 2 byte unsigned value
  876. I4 = 0x7, // 4 byte signed value
  877. U4 = 0x8, // 4 byte unsigned value
  878. I8 = 0x9, // 8 byte signed value
  879. U8 = 0xa, // 8 byte unsigned value
  880. R4 = 0xb, // 4 byte floating point
  881. R8 = 0xc, // 8 byte floating point
  882. Currency = 0xf, // A currency
  883. BStr = 0x13, // OLE Unicode BSTR
  884. LPStr = 0x14, // Ptr to SBCS string
  885. LPWStr = 0x15, // Ptr to Unicode string
  886. LPTStr = 0x16, // Ptr to OS preferred (SBCS/Unicode) string
  887. ByValTStr = 0x17, // OS preferred (SBCS/Unicode) inline string (only valid in structs)
  888. IUnknown = 0x19, // COM IUnknown pointer.
  889. IDispatch = 0x1a, // COM IDispatch pointer
  890. Struct = 0x1b, // Structure
  891. Interface = 0x1c, // COM interface
  892. SafeArray = 0x1d, // OLE SafeArray
  893. ByValArray = 0x1e, // Array of fixed size (only valid in structs)
  894. SysInt = 0x1f, // Hardware natural sized signed integer
  895. SysUInt = 0x20,
  896. VBByRefStr = 0x22,
  897. AnsiBStr = 0x23, // OLE BSTR containing SBCS characters
  898. TBStr = 0x24, // Ptr to OS preferred (SBCS/Unicode) BSTR
  899. VariantBool = 0x25, // OLE defined BOOLEAN (2 bytes, true == -1, false == 0)
  900. FunctionPtr = 0x26, // Function pointer
  901. AsAny = 0x28, // Paired with Object type and does runtime marshalling determination
  902. LPArray = 0x2a, // C style array
  903. LPStruct = 0x2b, // Pointer to a structure
  904. CustomMarshaler = 0x2c, // Native type supplied by custom code
  905. Error = 0x2d,
  906. NotSpecified = 0x50,
  907. }
  908. ///0-: Common
  909. ///1000-: HScript
  910. ///2000-: EcmaScript
  911. ///3000-: Zonnon
  912. ///4000-: Comega
  913. ///5000-: X++
  914. ///6000-: Spec#
  915. ///7000-: Sing#
  916. ///8000-: Xaml
  917. ///9000-: C/AL
  918. ///For your range contact hermanv@microsoft.com
  919. public enum NodeType
  920. {
  921. //Dummy
  922. Undefined = 0,
  923. //IL instruction node tags
  924. Add,
  925. Add_Ovf,
  926. Add_Ovf_Un,
  927. And,
  928. Arglist,
  929. Box,
  930. Branch,
  931. Call,
  932. Calli,
  933. Callvirt,
  934. Castclass,
  935. Ceq,
  936. Cgt,
  937. Cgt_Un,
  938. Ckfinite,
  939. Clt,
  940. Clt_Un,
  941. Conv_I,
  942. Conv_I1,
  943. Conv_I2,
  944. Conv_I4,
  945. Conv_I8,
  946. Conv_Ovf_I,
  947. Conv_Ovf_I_Un,
  948. Conv_Ovf_I1,
  949. Conv_Ovf_I1_Un,
  950. Conv_Ovf_I2,
  951. Conv_Ovf_I2_Un,
  952. Conv_Ovf_I4,
  953. Conv_Ovf_I4_Un,
  954. Conv_Ovf_I8,
  955. Conv_Ovf_I8_Un,
  956. Conv_Ovf_U,
  957. Conv_Ovf_U_Un,
  958. Conv_Ovf_U1,
  959. Conv_Ovf_U1_Un,
  960. Conv_Ovf_U2,
  961. Conv_Ovf_U2_Un,
  962. Conv_Ovf_U4,
  963. Conv_Ovf_U4_Un,
  964. Conv_Ovf_U8,
  965. Conv_Ovf_U8_Un,
  966. Conv_R_Un,
  967. Conv_R4,
  968. Conv_R8,
  969. Conv_U,
  970. Conv_U1,
  971. Conv_U2,
  972. Conv_U4,
  973. Conv_U8,
  974. Cpblk,
  975. DebugBreak,
  976. Div,
  977. Div_Un,
  978. Dup,
  979. EndFilter,
  980. EndFinally,
  981. ExceptionHandler,
  982. Initblk,
  983. Isinst,
  984. Jmp,
  985. Ldftn,
  986. Ldlen,
  987. Ldtoken,
  988. Ldvirtftn,
  989. Localloc,
  990. Mkrefany,
  991. Mul,
  992. Mul_Ovf,
  993. Mul_Ovf_Un,
  994. Neg,
  995. Nop,
  996. Not,
  997. Or,
  998. Pop,
  999. ReadOnlyAddressOf,
  1000. Refanytype,
  1001. Refanyval,
  1002. Rem,
  1003. Rem_Un,
  1004. Rethrow,
  1005. Shl,
  1006. Shr,
  1007. Shr_Un,
  1008. Sizeof,
  1009. SkipCheck,
  1010. Sub,
  1011. Sub_Ovf,
  1012. Sub_Ovf_Un,
  1013. SwitchInstruction,
  1014. Throw,
  1015. Unbox,
  1016. UnboxAny,
  1017. Xor,
  1018. //AST tags that are relevant to the binary reader
  1019. AddressDereference,
  1020. AddressOf,
  1021. AssignmentStatement,
  1022. Block,
  1023. Catch,
  1024. Construct,
  1025. ConstructArray,
  1026. Eq,
  1027. ExpressionStatement,
  1028. FaultHandler,
  1029. Filter,
  1030. Finally,
  1031. Ge,
  1032. Gt,
  1033. Identifier,
  1034. Indexer,
  1035. Instruction,
  1036. InterfaceExpression,
  1037. Le,
  1038. Literal,
  1039. LogicalNot,
  1040. Lt,
  1041. MemberBinding,
  1042. NamedArgument,
  1043. Namespace,
  1044. Ne,
  1045. Return,
  1046. This,
  1047. Try,
  1048. //Metadata node tags
  1049. ArrayType,
  1050. @Assembly,
  1051. AssemblyReference,
  1052. Attribute,
  1053. Class,
  1054. ClassParameter,
  1055. DelegateNode,
  1056. EnumNode,
  1057. Event,
  1058. Field,
  1059. FunctionPointer,
  1060. InstanceInitializer,
  1061. Interface,
  1062. Local,
  1063. Method,
  1064. Module,
  1065. ModuleReference,
  1066. OptionalModifier,
  1067. Parameter,
  1068. Pointer,
  1069. Property,
  1070. Reference,
  1071. RequiredModifier,
  1072. SecurityAttribute,
  1073. StaticInitializer,
  1074. Struct,
  1075. TypeParameter,
  1076. // The following NodeType definitions are not required
  1077. // for examining assembly metadata directly from binaries
  1078. //Serialization tags used for values that are not leaf nodes.
  1079. Array,
  1080. BlockReference,
  1081. CompilationParameters,
  1082. Document,
  1083. EndOfRecord,
  1084. Expression,
  1085. Guid,
  1086. List,
  1087. MarshallingInformation,
  1088. Member,
  1089. MemberReference,
  1090. MissingBlockReference,
  1091. MissingExpression,
  1092. MissingMemberReference,
  1093. String,
  1094. StringDictionary,
  1095. TypeNode,
  1096. Uri,
  1097. XmlNode,
  1098. //Source-based AST node tags
  1099. AddEventHandler,
  1100. AliasDefinition,
  1101. AnonymousNestedFunction,
  1102. ApplyToAll,
  1103. ArglistArgumentExpression,
  1104. ArglistExpression,
  1105. ArrayTypeExpression,
  1106. As,
  1107. Assertion,
  1108. AssignmentExpression,
  1109. Assumption,
  1110. Base,
  1111. BlockExpression,
  1112. BoxedTypeExpression,
  1113. ClassExpression,
  1114. CoerceTuple,
  1115. CollectionEnumerator,
  1116. Comma,
  1117. Compilation,
  1118. CompilationUnit,
  1119. CompilationUnitSnippet,
  1120. Conditional,
  1121. ConstructDelegate,
  1122. ConstructFlexArray,
  1123. ConstructIterator,
  1124. ConstructTuple,
  1125. Continue,
  1126. CopyReference,
  1127. CurrentClosure,
  1128. Decrement,
  1129. DefaultValue,
  1130. DoWhile,
  1131. Exit,
  1132. ExplicitCoercion,
  1133. ExpressionSnippet,
  1134. FieldInitializerBlock,
  1135. Fixed,
  1136. FlexArrayTypeExpression,
  1137. For,
  1138. ForEach,
  1139. FunctionDeclaration,
  1140. FunctionTypeExpression,
  1141. Goto,
  1142. GotoCase,
  1143. If,
  1144. ImplicitThis,
  1145. Increment,
  1146. InvariantTypeExpression,
  1147. Is,
  1148. LabeledStatement,
  1149. LocalDeclaration,
  1150. LocalDeclarationsStatement,
  1151. Lock,
  1152. LogicalAnd,
  1153. LogicalOr,
  1154. LRExpression,
  1155. MethodCall,
  1156. NameBinding,
  1157. NonEmptyStreamTypeExpression,
  1158. NonNullableTypeExpression,
  1159. NonNullTypeExpression,
  1160. NullableTypeExpression,
  1161. NullCoalesingExpression,
  1162. OutAddress,
  1163. Parentheses,
  1164. PointerTypeExpression,
  1165. PostfixExpression,
  1166. PrefixExpression,
  1167. QualifiedIdentifer,
  1168. RefAddress,
  1169. ReferenceTypeExpression,
  1170. RefTypeExpression,
  1171. RefValueExpression,
  1172. RemoveEventHandler,
  1173. Repeat,
  1174. ResourceUse,
  1175. SetterValue,
  1176. StackAlloc,
  1177. StatementSnippet,
  1178. StreamTypeExpression,
  1179. Switch,
  1180. SwitchCase,
  1181. SwitchCaseBottom,
  1182. TemplateInstance,
  1183. TupleTypeExpression,
  1184. TypeExpression,
  1185. TypeIntersectionExpression,
  1186. TypeMemberSnippet,
  1187. Typeof,
  1188. TypeReference,
  1189. Typeswitch,
  1190. TypeswitchCase,
  1191. TypeUnionExpression,
  1192. UnaryPlus,
  1193. UsedNamespace,
  1194. VariableDeclaration,
  1195. While,
  1196. Yield,
  1197. //Extended metadata node tags
  1198. ConstrainedType,
  1199. TupleType,
  1200. TypeAlias,
  1201. TypeIntersection,
  1202. TypeUnion,
  1203. //Query node tags
  1204. Composition,
  1205. QueryAggregate,
  1206. QueryAlias,
  1207. QueryAll,
  1208. QueryAny,
  1209. QueryAxis,
  1210. QueryCommit,
  1211. QueryContext,
  1212. QueryDelete,
  1213. QueryDifference,
  1214. QueryDistinct,
  1215. QueryExists,
  1216. QueryFilter,
  1217. QueryGeneratedType,
  1218. QueryGroupBy,
  1219. QueryInsert,
  1220. QueryIntersection,
  1221. QueryIterator,
  1222. QueryJoin,
  1223. QueryLimit,
  1224. QueryOrderBy,
  1225. QueryOrderItem,
  1226. QueryPosition,
  1227. QueryProject,
  1228. QueryQuantifiedExpression,
  1229. QueryRollback,
  1230. QuerySelect,
  1231. QuerySingleton,
  1232. QueryTransact,
  1233. QueryTypeFilter,
  1234. QueryUnion,
  1235. QueryUpdate,
  1236. QueryYielder,
  1237. //Contract node tags
  1238. Acquire,
  1239. Comprehension,
  1240. ComprehensionBinding,
  1241. Ensures,
  1242. EnsuresExceptional,
  1243. EnsuresNormal,
  1244. Iff,
  1245. Implies,
  1246. Invariant,
  1247. LogicalEqual,
  1248. LogicalImply,
  1249. Maplet,
  1250. MethodContract,
  1251. Modelfield,
  1252. ModelfieldContract,
  1253. OldExpression,
  1254. Range,
  1255. Read,
  1256. Requires,
  1257. RequiresOtherwise,
  1258. RequiresPlain,
  1259. TypeContract,
  1260. Write,
  1261. //Node tags for explicit modifiers in front-end
  1262. OptionalModifierTypeExpression,
  1263. RequiredModifierTypeExpression,
  1264. //Temporary node tags
  1265. Count,
  1266. Exists,
  1267. ExistsUnique,
  1268. Forall,
  1269. Max,
  1270. Min,
  1271. Product,
  1272. Sum,
  1273. Quantifier,
  1274. }
  1275. [Flags]
  1276. public enum AssemblyFlags
  1277. {
  1278. None = 0x0000,
  1279. PublicKey = 0x0001,
  1280. Library = 0x0002,
  1281. Platform = 0x0004,
  1282. NowPlatform = 0x0006,
  1283. SideBySideCompatible = 0x0000,
  1284. NonSideBySideCompatible = 0x0010,
  1285. NonSideBySideProcess = 0x0020,
  1286. NonSideBySideMachine = 0x0030,
  1287. CompatibilityMask = 0x00F0,
  1288. Retargetable = 0x0100,
  1289. DisableJITcompileOptimizer = 0x4000,
  1290. EnableJITcompileTracking = 0x8000
  1291. }
  1292. public enum AssemblyHashAlgorithm
  1293. {
  1294. None = 0x0000,
  1295. MD5 = 0x8003,
  1296. SHA1 = 0x8004
  1297. }
  1298. [Flags]
  1299. public enum CallingConventionFlags
  1300. {
  1301. Default = 0x0,
  1302. C = 0x1,
  1303. StandardCall = 0x2,
  1304. ThisCall = 0x3,
  1305. FastCall = 0x4,
  1306. VarArg = 0x5,
  1307. ArgumentConvention = 0x7,
  1308. Generic = 0x10,
  1309. HasThis = 0x20,
  1310. ExplicitThis = 0x40
  1311. }
  1312. [Flags]
  1313. public enum EventFlags
  1314. {
  1315. None = 0x0000,
  1316. SpecialName = 0x0200,
  1317. ReservedMask = 0x0400,
  1318. RTSpecialName = 0x0400,
  1319. Extend = MethodFlags.Extend, // used for languages with type extensions, e.g. Sing#
  1320. }
  1321. [Flags]
  1322. public enum FieldFlags
  1323. {
  1324. None = 0x0000,
  1325. FieldAccessMask = 0x0007,
  1326. CompilerControlled = 0x0000,
  1327. Private = 0x0001,
  1328. FamANDAssem = 0x0002,
  1329. Assembly = 0x0003,
  1330. Family = 0x0004,
  1331. FamORAssem = 0x0005,
  1332. Public = 0x0006,
  1333. Static = 0x0010,
  1334. InitOnly = 0x0020,
  1335. Literal = 0x0040,
  1336. NotSerialized = 0x0080,
  1337. SpecialName = 0x0200,
  1338. PinvokeImpl = 0x2000,
  1339. ReservedMask = 0x9500,
  1340. RTSpecialName = 0x0400,
  1341. HasFieldMarshal = 0x1000,
  1342. HasDefault = 0x8000,
  1343. HasFieldRVA = 0x0100,
  1344. }
  1345. [Flags]
  1346. public enum FileFlags
  1347. {
  1348. ContainsMetaData = 0x0000,
  1349. ContainsNoMetaData = 0x0001
  1350. }
  1351. [Flags]
  1352. public enum TypeParameterFlags
  1353. {
  1354. NonVariant = 0x0000,
  1355. Covariant = 0x0001,
  1356. Contravariant = 0x0002,
  1357. VarianceMask = 0x0003,
  1358. NoSpecialConstraint = 0x0000,
  1359. ReferenceTypeConstraint = 0x0004,
  1360. ValueTypeConstraint = 0x0008,
  1361. DefaultConstructorConstraint = 0x0010,
  1362. SpecialConstraintMask = 0x001C,
  1363. }
  1364. [Flags]
  1365. public enum MethodImplFlags
  1366. {
  1367. CodeTypeMask = 0x0003,
  1368. IL = 0x0000,
  1369. Native = 0x0001,
  1370. OPTIL = 0x0002,
  1371. Runtime = 0x0003,
  1372. ManagedMask = 0x0004,
  1373. Unmanaged = 0x0004,
  1374. Managed = 0x0000,
  1375. ForwardRef = 0x0010,
  1376. PreserveSig = 0x0080,
  1377. InternalCall = 0x1000,
  1378. Synchronized = 0x0020,
  1379. NoInlining = 0x0008,
  1380. MaxMethodImplVal = 0xffff
  1381. }
  1382. [Flags]
  1383. public enum MethodFlags
  1384. {
  1385. MethodAccessMask = 0x0007,
  1386. CompilerControlled = 0x0000,
  1387. Private = 0x0001,
  1388. FamANDAssem = 0x0002,
  1389. Assembly = 0x0003,
  1390. Family = 0x0004,
  1391. FamORAssem = 0x0005,
  1392. Public = 0x0006,
  1393. Static = 0x0010,
  1394. Final = 0x0020,
  1395. Virtual = 0x0040,
  1396. HideBySig = 0x0080,
  1397. VtableLayoutMask = 0x0100,
  1398. ReuseSlot = 0x0000,
  1399. NewSlot = 0x0100,
  1400. CheckAccessOnOverride = 0x0200,
  1401. Abstract = 0x0400,
  1402. SpecialName = 0x0800,
  1403. PInvokeImpl = 0x2000,
  1404. UnmanagedExport = 0xd000,
  1405. ReservedMask = 0xd000,
  1406. RTSpecialName = 0x1000,
  1407. HasSecurity = 0x4000,
  1408. RequireSecObject = 0x8000,
  1409. Extend = 0x01000000, // used for languages with type extensions, e.g. Sing#
  1410. }
  1411. public enum ModuleKind
  1412. {
  1413. ConsoleApplication,
  1414. WindowsApplication,
  1415. DynamicallyLinkedLibrary,
  1416. ManifestResourceFile,
  1417. UnmanagedDynamicallyLinkedLibrary
  1418. }
  1419. [Flags]
  1420. public enum ParameterFlags
  1421. {
  1422. None = 0x0000,
  1423. In = 0x0001,
  1424. Out = 0x0002,
  1425. Optional = 0x0010,
  1426. ReservedMask = 0xf000,
  1427. HasDefault = 0x1000,
  1428. HasFieldMarshal = 0x2000
  1429. }
  1430. [Flags]
  1431. public enum PEKindFlags
  1432. {
  1433. ILonly = 0x0001,
  1434. Requires32bits = 0x0002,
  1435. Requires64bits = 0x0004,
  1436. AMD = 0x0008
  1437. }
  1438. [Flags]
  1439. public enum PInvokeFlags
  1440. {
  1441. None = 0x0000,
  1442. NoMangle = 0x0001,
  1443. BestFitDisabled = 0x0020,
  1444. BestFitEnabled = 0x0010,
  1445. BestFitUseAsm = 0x0000,
  1446. BestFitMask = 0x0030,
  1447. CharSetMask = 0x0006,
  1448. CharSetNotSpec = 0x0000,
  1449. CharSetAns = 0x0002,
  1450. CharSetUnicode = 0x0004,
  1451. CharSetAuto = 0x0006,
  1452. SupportsLastError = 0x0040,
  1453. CallingConvMask = 0x0700,
  1454. CallConvWinapi = 0x0100,
  1455. CallConvCdecl = 0x0200,
  1456. CallConvStdcall = 0x0300,
  1457. CallConvThiscall = 0x0400,
  1458. CallConvFastcall = 0x0500,
  1459. ThrowOnUnmappableCharMask = 0x3000,
  1460. ThrowOnUnmappableCharEnabled = 0x1000,
  1461. ThrowOnUnmappableCharDisabled = 0x2000,
  1462. ThrowOnUnmappableCharUseAsm = 0x0000
  1463. }
  1464. [Flags]
  1465. public enum PropertyFlags
  1466. {
  1467. None = 0x0000,
  1468. SpecialName = 0x0200,
  1469. ReservedMask = 0xf400,
  1470. RTSpecialName = 0x0400,
  1471. Extend = MethodFlags.Extend, // used for languages with type extensions, e.g. Sing#
  1472. }
  1473. public enum PESection
  1474. {
  1475. Text,
  1476. SData,
  1477. TLS
  1478. };
  1479. [Flags]
  1480. public enum TypeFlags
  1481. {
  1482. None = 0x00000000,
  1483. VisibilityMask = 0x00000007,
  1484. NotPublic = 0x00000000,
  1485. Public = 0x00000001,
  1486. NestedPublic = 0x00000002,
  1487. NestedPrivate = 0x00000003,
  1488. NestedFamily = 0x00000004,
  1489. NestedAssembly = 0x00000005,
  1490. NestedFamANDAssem = 0x00000006,
  1491. NestedFamORAssem = 0x00000007,
  1492. LayoutMask = 0x00000018,
  1493. AutoLayout = 0x00000000,
  1494. SequentialLayout = 0x00000008,
  1495. ExplicitLayout = 0x00000010,
  1496. ClassSemanticsMask = 0x00000020,
  1497. Class = 0x00000000,
  1498. Interface = 0x00000020,
  1499. LayoutOverridden = 0x00000040, // even AutoLayout can be explicit or implicit
  1500. Abstract = 0x00000080,
  1501. Sealed = 0x00000100,
  1502. SpecialName = 0x00000400,
  1503. Import = 0x00001000,
  1504. Serializable = 0x00002000,
  1505. StringFormatMask = 0x00030000,
  1506. AnsiClass = 0x00000000,
  1507. UnicodeClass = 0x00010000,
  1508. AutoClass = 0x00020000,
  1509. BeforeFieldInit = 0x00100000,
  1510. ReservedMask = 0x00040800,
  1511. RTSpecialName = 0x00000800,
  1512. HasSecurity = 0x00040000,
  1513. Forwarder = 0x00200000, //The type is a stub left behind for backwards compatibility. References to this type are forwarded to another type by the CLR.
  1514. Extend = 0x01000000, // used for languages with type extensions, e.g. Sing#
  1515. }
  1516. public sealed class TrivialHashtable
  1517. {
  1518. struct HashEntry
  1519. {
  1520. public int Key;
  1521. public object Value;
  1522. }
  1523. private HashEntry[]/*!*/ entries;
  1524. private int count;
  1525. public TrivialHashtable()
  1526. {
  1527. this.entries = new HashEntry[16];
  1528. //this.count = 0;
  1529. }
  1530. private TrivialHashtable(HashEntry[]/*!*/ entries, int count)
  1531. {
  1532. this.entries = entries;
  1533. this.count = count;
  1534. }
  1535. public TrivialHashtable(int expectedEntries)
  1536. {
  1537. int initialSize = 16;
  1538. expectedEntries <<= 1;
  1539. while(initialSize < expectedEntries && initialSize > 0)
  1540. initialSize <<= 1;
  1541. if(initialSize < 0)
  1542. initialSize = 16;
  1543. this.entries = new HashEntry[initialSize];
  1544. //this.count = 0;
  1545. }
  1546. public int Count
  1547. {
  1548. get
  1549. {
  1550. return this.count;
  1551. }
  1552. }
  1553. private void Expand()
  1554. {
  1555. HashEntry[] oldEntries = this.entries;
  1556. int n = oldEntries.Length;
  1557. int m = n * 2;
  1558. if(m <= 0)
  1559. return;
  1560. HashEntry[] entries = new HashEntry[m];
  1561. int count = 0;
  1562. for(int i = 0; i < n; i++)
  1563. {
  1564. int key = oldEntries[i].Key;
  1565. if(key <= 0)
  1566. continue; //No entry (0) or deleted entry (-1)
  1567. object value = oldEntries[i].Value;
  1568. Debug.Assert(value != null);
  1569. int j = key & (m - 1);
  1570. int k = entries[j].Key;
  1571. while(true)
  1572. {
  1573. if(k == 0)
  1574. {
  1575. entries[j].Value = value;
  1576. entries[j].Key = key;
  1577. count++;
  1578. break;
  1579. }
  1580. j++;
  1581. if(j >= m)
  1582. j = 0;
  1583. k = entries[j].Key;
  1584. }
  1585. }
  1586. this.entries = entries;
  1587. this.count = count;
  1588. }
  1589. public object this[int key]
  1590. {
  1591. get
  1592. {
  1593. if(key <= 0)
  1594. throw new ArgumentException(ExceptionStrings.KeyNeedsToBeGreaterThanZero, "key");
  1595. HashEntry[] entries = this.entries;
  1596. int n = entries.Length;
  1597. int i = key & (n - 1);
  1598. int k = entries[i].Key;
  1599. object result = null;
  1600. while(true)
  1601. {
  1602. if(k == key) { result = entries[i].Value; break; }
  1603. if(k == 0)
  1604. break;
  1605. i++;
  1606. if(i >= n)
  1607. i = 0;
  1608. k = entries[i].Key;
  1609. }
  1610. return result;
  1611. }
  1612. set
  1613. {
  1614. if(key <= 0)
  1615. throw new ArgumentException(ExceptionStrings.KeyNeedsToBeGreaterThanZero, "key");
  1616. HashEntry[] entries = this.entries;
  1617. int n = entries.Length;
  1618. int i = key & (n - 1);
  1619. int k = entries[i].Key;
  1620. while(true)
  1621. {
  1622. if(k == key || k == 0)
  1623. {
  1624. entries[i].Value = value;
  1625. if(k == 0)
  1626. {
  1627. if(value == null) { return; }
  1628. entries[i].Key = key;
  1629. if(++this.count > n / 2)
  1630. this.Expand();
  1631. return;
  1632. }
  1633. if(value == null)
  1634. entries[i].Key = -1;
  1635. return;
  1636. }
  1637. i++;
  1638. if(i >= n)
  1639. i = 0;
  1640. k = entries[i].Key;
  1641. }
  1642. }
  1643. }
  1644. public TrivialHashtable Clone()
  1645. {
  1646. HashEntry[] clonedEntries = (HashEntry[])this.entries.Clone();
  1647. //^ assume clonedEntries != null;
  1648. return new TrivialHashtable(clonedEntries, this.count);
  1649. }
  1650. }
  1651. public sealed class TrivialHashtableUsingWeakReferences
  1652. {
  1653. struct HashEntry
  1654. {
  1655. public int Key;
  1656. public WeakReference Value;
  1657. }
  1658. private HashEntry[]/*!*/ entries;
  1659. private int count;
  1660. public TrivialHashtableUsingWeakReferences()
  1661. {
  1662. this.entries = new HashEntry[16];
  1663. //this.count = 0;
  1664. }
  1665. private TrivialHashtableUsingWeakReferences(HashEntry[]/*!*/ entries, int count)
  1666. {
  1667. this.entries = entries;
  1668. this.count = count;
  1669. }
  1670. public TrivialHashtableUsingWeakReferences(int expectedEntries)
  1671. {
  1672. int initialSize = 16;
  1673. expectedEntries <<= 1;
  1674. while(initialSize < expectedEntries && initialSize > 0)
  1675. initialSize <<= 1;
  1676. if(initialSize < 0)
  1677. initialSize = 16;
  1678. this.entries = new HashEntry[initialSize];
  1679. //this.count = 0;
  1680. }
  1681. public int Count
  1682. {
  1683. get
  1684. {
  1685. return this.count;
  1686. }
  1687. }
  1688. private void Expand()
  1689. {
  1690. HashEntry[] oldEntries = this.entries;
  1691. int n = oldEntries.Length;
  1692. int m = n * 2;
  1693. if(m <= 0)
  1694. return;
  1695. HashEntry[] entries = new HashEntry[m];
  1696. int count = 0;
  1697. for(int i = 0; i < n; i++)
  1698. {
  1699. int key = oldEntries[i].Key;
  1700. if(key <= 0)
  1701. continue; //No entry (0) or deleted entry (-1)
  1702. WeakReference value = oldEntries[i].Value;
  1703. Debug.Assert(value != null);
  1704. if(value == null || !value.IsAlive)
  1705. continue; //Collected entry.
  1706. int j = key & (m - 1);
  1707. int k = entries[j].Key;
  1708. while(true)
  1709. {
  1710. if(k == 0)
  1711. {
  1712. entries[j].Value = value;
  1713. entries[j].Key = key;
  1714. count++;
  1715. break;
  1716. }
  1717. j++;
  1718. if(j >= m)
  1719. j = 0;
  1720. k = entries[j].Key;
  1721. }
  1722. }
  1723. this.entries = entries;
  1724. this.count = count;
  1725. }
  1726. private void Contract()
  1727. {
  1728. HashEntry[] oldEntries = this.entries;
  1729. int n = oldEntries.Length;
  1730. int m = n / 2;
  1731. if(m < 16)
  1732. return;
  1733. HashEntry[] entries = new HashEntry[m];
  1734. int count = 0;
  1735. for(int i = 0; i < n; i++)
  1736. {
  1737. int key = oldEntries[i].Key;
  1738. if(key <= 0)
  1739. continue; //No entry (0) or deleted entry (-1)
  1740. WeakReference value = oldEntries[i].Value;
  1741. Debug.Assert(value != null);
  1742. if(value == null || !value.IsAlive)
  1743. continue; //Collected entry.
  1744. int j = key & (m - 1);
  1745. int k = entries[j].Key;
  1746. while(true)
  1747. {
  1748. if(k == 0)
  1749. {
  1750. entries[j].Value = value;
  1751. entries[j].Key = key;
  1752. count++;
  1753. break;
  1754. }
  1755. j++;
  1756. if(j >= m)
  1757. j = 0;
  1758. k = entries[j].Key;
  1759. }
  1760. }
  1761. this.entries = entries;
  1762. this.count = count;
  1763. }
  1764. private void WeedOutCollectedEntries()
  1765. {
  1766. HashEntry[] oldEntries = this.entries;
  1767. int n = oldEntries.Length;
  1768. HashEntry[] entries = new HashEntry[n];
  1769. int count = 0;
  1770. for(int i = 0; i < n; i++)
  1771. {
  1772. int key = oldEntries[i].Key;
  1773. if(key <= 0)
  1774. continue; //No entry (0) or deleted entry (-1)
  1775. WeakReference value = oldEntries[i].Value;
  1776. Debug.Assert(value != null);
  1777. if(value == null || !value.IsAlive)
  1778. continue; //Collected entry.
  1779. int j = key & (n - 1);
  1780. int k = entries[j].Key;
  1781. while(true)
  1782. {
  1783. if(k == 0)
  1784. {
  1785. entries[j].Value = value;
  1786. entries[j].Key = key;
  1787. count++;
  1788. break;
  1789. }
  1790. j++;
  1791. if(j >= n)
  1792. j = 0;
  1793. k = entries[j].Key;
  1794. }
  1795. }
  1796. this.entries = entries;
  1797. this.count = count;
  1798. }
  1799. public object this[int key]
  1800. {
  1801. get
  1802. {
  1803. if(key <= 0)
  1804. throw new ArgumentException(ExceptionStrings.KeyNeedsToBeGreaterThanZero, "key");
  1805. HashEntry[] entries = this.entries;
  1806. int n = entries.Length;
  1807. int i = key & (n - 1);
  1808. int k = entries[i].Key;
  1809. object result = null;
  1810. while(true)
  1811. {
  1812. if(k == key)
  1813. {
  1814. WeakReference wref = entries[i].Value;
  1815. if(wref == null) { Debug.Assert(false); return null; }
  1816. result = wref.Target;
  1817. if(result != null)
  1818. return result;
  1819. this.WeedOutCollectedEntries();
  1820. while(this.count < n / 4 && n > 16) { this.Contract(); n = this.entries.Length; }
  1821. return null;
  1822. }
  1823. if(k == 0)
  1824. break;
  1825. i++;
  1826. if(i >= n)
  1827. i = 0;
  1828. k = entries[i].Key;
  1829. }
  1830. return result;
  1831. }
  1832. set
  1833. {
  1834. if(key <= 0)
  1835. throw new ArgumentException(ExceptionStrings.KeyNeedsToBeGreaterThanZero, "key");
  1836. HashEntry[] entries = this.entries;
  1837. int n = entries.Length;
  1838. int i = key & (n - 1);
  1839. int k = entries[i].Key;
  1840. while(true)
  1841. {
  1842. if(k == key || k == 0)
  1843. {
  1844. if(value == null)
  1845. entries[i].Value = null;
  1846. else
  1847. entries[i].Value = new WeakReference(value);
  1848. if(k == 0)
  1849. {
  1850. if(value == null)
  1851. return;
  1852. entries[i].Key = key;
  1853. if(++this.count > n / 2)
  1854. {
  1855. this.Expand(); //Could decrease this.count because of collected entries being deleted
  1856. while(this.count < n / 4 && n > 16) { this.Contract(); n = this.entries.Length; }
  1857. }
  1858. return;
  1859. }
  1860. if(value == null)
  1861. entries[i].Key = -1;
  1862. return;
  1863. }
  1864. i++;
  1865. if(i >= n)
  1866. i = 0;
  1867. k = entries[i].Key;
  1868. }
  1869. }
  1870. }
  1871. public TrivialHashtableUsingWeakReferences Clone()
  1872. {
  1873. HashEntry[] clonedEntries = (HashEntry[])this.entries.Clone();
  1874. //^ assume clonedEntries != null;
  1875. return new TrivialHashtableUsingWeakReferences(clonedEntries, this.count);
  1876. }
  1877. }
  1878. public interface IUniqueKey
  1879. {
  1880. int UniqueId { get; }
  1881. }
  1882. /// <summary>
  1883. /// A node in an Abstract Syntax Tree.
  1884. /// </summary>
  1885. public abstract class Node : IUniqueKey
  1886. {
  1887. public bool IsErroneous;
  1888. /// <summary>
  1889. /// The region in the source code that contains the concrete syntax corresponding to this node in the Abstract Syntax Tree.
  1890. /// </summary>
  1891. public SourceContext SourceContext;
  1892. #if DEBUG
  1893. public string DebugLabel; // useful for debugging.
  1894. #endif
  1895. protected Node(NodeType nodeType)
  1896. {
  1897. this.NodeType = nodeType;
  1898. }
  1899. private NodeType nodeType;
  1900. /// <summary>
  1901. /// A scalar tag that identifies the concrete type of the node. This is provided to allow efficient type membership tests that
  1902. /// facilitate tree traversal.
  1903. /// </summary>
  1904. public NodeType NodeType
  1905. {
  1906. get { return this.nodeType; }
  1907. set { this.nodeType = value; }
  1908. }
  1909. private static int uniqueKeyCounter;
  1910. private int uniqueKey;
  1911. /// <summary>
  1912. /// An integer that uniquely identifies this node. This provides an efficient equality test to facilitate hashing.
  1913. /// Do not override this.
  1914. /// </summary>
  1915. public virtual int UniqueKey
  1916. {
  1917. get
  1918. {
  1919. if(this.uniqueKey == 0)
  1920. {
  1921. TryAgain:
  1922. int c = Node.uniqueKeyCounter;
  1923. int cp1 = c + 17;
  1924. if(cp1 <= 0)
  1925. cp1 = 1000000;
  1926. if(System.Threading.Interlocked.CompareExchange(ref Node.uniqueKeyCounter, cp1, c) != c)
  1927. goto TryAgain;
  1928. this.uniqueKey = cp1;
  1929. }
  1930. return this.uniqueKey;
  1931. }
  1932. }
  1933. /// <summary>
  1934. /// Makes a shallow copy of the node.
  1935. /// </summary>
  1936. /// <returns>A shallow copy of the node</returns>
  1937. public virtual Node/*!*/ Clone()
  1938. {
  1939. Node result = (Node)this.MemberwiseClone();
  1940. result.uniqueKey = 0;
  1941. return result;
  1942. }
  1943. public virtual object GetVisitorFor(object/*!*/ callingVisitor, string/*!*/ visitorClassName)
  1944. {
  1945. if(callingVisitor == null || visitorClassName == null) { Debug.Fail(""); return null; }
  1946. return Node.GetVisitorFor(this.GetType(), callingVisitor, visitorClassName);
  1947. }
  1948. private static Hashtable VisitorTypeFor; //contains weak references
  1949. private static Object GetVisitorFor(System.Type/*!*/ nodeType, object/*!*/ callingVisitor, string/*!*/ visitorClassName)
  1950. {
  1951. if(nodeType == null || callingVisitor == null || visitorClassName == null) { Debug.Fail(""); return null; }
  1952. if(Node.VisitorTypeFor == null)
  1953. Node.VisitorTypeFor = new Hashtable();
  1954. string customVisitorClassName = visitorClassName;
  1955. if(visitorClassName.IndexOf('.') < 0)
  1956. customVisitorClassName = nodeType.Namespace + "." + visitorClassName;
  1957. if(customVisitorClassName == callingVisitor.GetType().FullName)
  1958. {
  1959. Debug.Assert(false); //This must be a bug, the calling visitor is the one that should handle the nodeType
  1960. return null;
  1961. }
  1962. System.Reflection.AssemblyName visitorAssemblyName = null;
  1963. System.Reflection.Assembly assembly = null;
  1964. WeakReference wref = (WeakReference)Node.VisitorTypeFor[customVisitorClassName];
  1965. Type visitorType = wref == null ? null : (System.Type)wref.Target;
  1966. if(visitorType == typeof(object))
  1967. return null;
  1968. string callerDirectory = null;
  1969. if(visitorType == null)
  1970. {
  1971. assembly = nodeType.Assembly;
  1972. if(assembly == null)
  1973. return null;
  1974. visitorType = assembly.GetType(customVisitorClassName, false);
  1975. }
  1976. if(visitorType == null)
  1977. {
  1978. //^ assert assembly != null;
  1979. if(assembly.Location == null)
  1980. return null;
  1981. callerDirectory = Path.GetDirectoryName(assembly.Location);
  1982. visitorAssemblyName = new System.Reflection.AssemblyName();
  1983. visitorAssemblyName.Name = "Visitors";
  1984. visitorAssemblyName.CodeBase = "file:///" + Path.Combine(callerDirectory, "Visitors.dll");
  1985. try
  1986. {
  1987. assembly = System.Reflection.Assembly.Load(visitorAssemblyName);
  1988. }
  1989. catch { }
  1990. if(assembly != null)
  1991. visitorType = assembly.GetType(customVisitorClassName, false);
  1992. if(visitorType == null)
  1993. {
  1994. visitorAssemblyName.Name = customVisitorClassName;
  1995. visitorAssemblyName.CodeBase = "file:///" + Path.Combine(callerDirectory, customVisitorClassName + ".dll");
  1996. try
  1997. {
  1998. assembly = System.Reflection.Assembly.Load(visitorAssemblyName);
  1999. }
  2000. catch { }
  2001. if(assembly != null)
  2002. visitorType = assembly.GetType(customVisitorClassName, false);
  2003. }
  2004. }
  2005. if(visitorType == null)
  2006. {
  2007. //Put fake entry into hash table to short circuit future lookups
  2008. visitorType = typeof(object);
  2009. assembly = nodeType.Assembly;
  2010. }
  2011. if(assembly != null)
  2012. { //Only happens if there was a cache miss
  2013. lock(Node.VisitorTypeFor)
  2014. {
  2015. Node.VisitorTypeFor[customVisitorClassName] = new WeakReference(visitorType);
  2016. }
  2017. }
  2018. if(visitorType == typeof(object))
  2019. return null;
  2020. try
  2021. {
  2022. return System.Activator.CreateInstance(visitorType, new object[] { callingVisitor });
  2023. }
  2024. catch { }
  2025. return null;
  2026. }
  2027. int IUniqueKey.UniqueId { get { return this.UniqueKey; } }
  2028. }
  2029. public abstract class ErrorNode : Node
  2030. {
  2031. public int Code;
  2032. public string[] MessageParameters;
  2033. protected ErrorNode(int code, params string[] messageParameters)
  2034. : base(NodeType.Undefined)
  2035. {
  2036. this.Code = code;
  2037. this.MessageParameters = messageParameters;
  2038. }
  2039. public virtual string GetErrorNumber()
  2040. {
  2041. return this.Code.ToString("0000");
  2042. }
  2043. public string GetMessage()
  2044. {
  2045. return this.GetMessage(null);
  2046. }
  2047. public abstract string GetMessage(System.Globalization.CultureInfo culture);
  2048. public virtual string GetMessage(string key, System.Resources.ResourceManager rm, System.Globalization.CultureInfo culture)
  2049. {
  2050. if(rm == null || key == null)
  2051. return null;
  2052. string localizedString = rm.GetString(key, culture);
  2053. if(localizedString == null)
  2054. localizedString = key;
  2055. string[] messageParameters = this.MessageParameters;
  2056. if(messageParameters == null || messageParameters.Length == 0)
  2057. return localizedString;
  2058. return string.Format(localizedString, messageParameters);
  2059. }
  2060. public abstract int Severity
  2061. {
  2062. get;
  2063. }
  2064. public static int GetCountAtSeverity(ErrorNodeList errors, int minSeverity, int maxSeverity)
  2065. {
  2066. if(errors == null)
  2067. return 0;
  2068. int n = 0;
  2069. for(int i = 0; i < errors.Count; i++)
  2070. {
  2071. ErrorNode e = errors[i];
  2072. if(e == null)
  2073. continue;
  2074. int s = e.Severity;
  2075. if(minSeverity <= s && s <= maxSeverity)
  2076. n++;
  2077. }
  2078. return n;
  2079. }
  2080. }
  2081. public class Expose : Statement
  2082. {
  2083. public Expression Instance;
  2084. public Block Body;
  2085. public bool IsLocal;
  2086. public Expose(NodeType nodeType)
  2087. : base(nodeType)
  2088. {
  2089. }
  2090. }
  2091. public class Acquire : Statement
  2092. {
  2093. public bool ReadOnly;
  2094. public Statement Target;
  2095. public Expression Condition;
  2096. public Expression ConditionFunction;
  2097. public Block Body;
  2098. public BlockScope ScopeForTemporaryVariable;
  2099. public Acquire()
  2100. : base(NodeType.Acquire)
  2101. {
  2102. }
  2103. }
  2104. public class Expression : Node
  2105. {
  2106. private TypeNode type;
  2107. public Expression(NodeType nodeType)
  2108. : base(nodeType)
  2109. {
  2110. }
  2111. public Expression(NodeType nodeType, TypeNode type)
  2112. : base(nodeType)
  2113. {
  2114. this.type = type;
  2115. }
  2116. public virtual TypeNode Type
  2117. {
  2118. get { return this.type; }
  2119. set { this.type = value; }
  2120. }
  2121. }
  2122. public class ExpressionSnippet : Expression
  2123. {
  2124. public IParserFactory ParserFactory;
  2125. public ExpressionSnippet()
  2126. : base(NodeType.ExpressionSnippet)
  2127. {
  2128. }
  2129. public ExpressionSnippet(IParserFactory parserFactory, SourceContext sctx)
  2130. : base(NodeType.ExpressionSnippet)
  2131. {
  2132. this.ParserFactory = parserFactory;
  2133. this.SourceContext = sctx;
  2134. }
  2135. }
  2136. public class MemberBinding : Expression
  2137. {
  2138. private int alignment;
  2139. private Member boundMember;
  2140. public Expression BoundMemberExpression;
  2141. private Expression targetObject;
  2142. private bool @volatile;
  2143. public MemberBinding()
  2144. : base(NodeType.MemberBinding)
  2145. {
  2146. }
  2147. public MemberBinding(Expression targetObject, Member/*!*/ boundMember)
  2148. : this(targetObject, boundMember, false, -1)
  2149. {
  2150. if(boundMember is Field)
  2151. this.Volatile = ((Field)boundMember).IsVolatile;
  2152. }
  2153. public MemberBinding(Expression targetObject, Member/*!*/ boundMember, Expression boundMemberExpression)
  2154. : this(targetObject, boundMember, false, -1)
  2155. {
  2156. if(boundMember is Field)
  2157. this.Volatile = ((Field)boundMember).IsVolatile;
  2158. this.BoundMemberExpression = boundMemberExpression;
  2159. }
  2160. public MemberBinding(Expression targetObject, Member/*!*/ boundMember, SourceContext sctx)
  2161. : this(targetObject, boundMember, false, -1)
  2162. {
  2163. if(boundMember is Field)
  2164. this.Volatile = ((Field)boundMember).IsVolatile;
  2165. this.SourceContext = sctx;
  2166. }
  2167. public MemberBinding(Expression targetObject, Member/*!*/ boundMember, SourceContext sctx, Expression boundMemberExpression)
  2168. : this(targetObject, boundMember, false, -1)
  2169. {
  2170. if(boundMember is Field)
  2171. this.Volatile = ((Field)boundMember).IsVolatile;
  2172. this.SourceContext = sctx;
  2173. this.BoundMemberExpression = boundMemberExpression;
  2174. }
  2175. public MemberBinding(Expression targetObject, Member/*!*/ boundMember, bool @volatile, int alignment)
  2176. : base(NodeType.MemberBinding)
  2177. {
  2178. Debug.Assert(boundMember != null);
  2179. this.alignment = alignment;
  2180. this.boundMember = boundMember;
  2181. this.targetObject = targetObject;
  2182. this.@volatile = @volatile;
  2183. switch(boundMember.NodeType)
  2184. {
  2185. case NodeType.Field:
  2186. this.Type = ((Field)boundMember).Type;
  2187. break;
  2188. case NodeType.Method:
  2189. this.Type = ((Method)boundMember).ReturnType;
  2190. break;
  2191. case NodeType.Event:
  2192. this.Type = ((Event)boundMember).HandlerType;
  2193. break;
  2194. default:
  2195. this.Type = boundMember as TypeNode;
  2196. break;
  2197. }
  2198. }
  2199. public int Alignment
  2200. {
  2201. get { return this.alignment; }
  2202. set { this.alignment = value; }
  2203. }
  2204. public Member BoundMember
  2205. {
  2206. get { return this.boundMember; }
  2207. set { this.boundMember = value; }
  2208. }
  2209. public Expression TargetObject
  2210. {
  2211. get { return this.targetObject; }
  2212. set { this.targetObject = value; }
  2213. }
  2214. public bool Volatile
  2215. {
  2216. get { return this.@volatile; }
  2217. set { this.@volatile = value; }
  2218. }
  2219. }
  2220. public class AddressDereference : Expression
  2221. {
  2222. private Expression address;
  2223. private int alignment;
  2224. private bool isVolatile;
  2225. public enum ExplicitOp { None = 0, Star, Arrow }
  2226. private ExplicitOp explicitOperation; // was explicit in source (* or ->)
  2227. public AddressDereference()
  2228. : base(NodeType.AddressDereference)
  2229. {
  2230. }
  2231. public AddressDereference(Expression address, TypeNode type)
  2232. : this(address, type, false, -1)
  2233. {
  2234. }
  2235. public AddressDereference(Expression address, TypeNode type, SourceContext sctx)
  2236. : this(address, type, false, -1, sctx)
  2237. {
  2238. }
  2239. public AddressDereference(Expression address, TypeNode type, bool isVolatile, int alignment)
  2240. : base(NodeType.AddressDereference)
  2241. {
  2242. this.address = address;
  2243. this.alignment = alignment;
  2244. this.Type = type;
  2245. this.isVolatile = isVolatile;
  2246. }
  2247. public AddressDereference(Expression address, TypeNode type, bool Volatile, int alignment, SourceContext sctx)
  2248. : base(NodeType.AddressDereference)
  2249. {
  2250. this.address = address;
  2251. this.alignment = alignment;
  2252. this.Type = type;
  2253. this.isVolatile = Volatile;
  2254. this.SourceContext = sctx;
  2255. }
  2256. public Expression Address
  2257. {
  2258. get { return this.address; }
  2259. set { this.address = value; }
  2260. }
  2261. public int Alignment
  2262. {
  2263. get { return this.alignment; }
  2264. set { this.alignment = value; }
  2265. }
  2266. public bool Volatile
  2267. {
  2268. get { return this.isVolatile; }
  2269. set { this.isVolatile = value; }
  2270. }
  2271. public bool Explicit
  2272. {
  2273. get { return this.explicitOperation != ExplicitOp.None; }
  2274. }
  2275. public ExplicitOp ExplicitOperator
  2276. {
  2277. get { return this.explicitOperation; }
  2278. set { this.explicitOperation = value; }
  2279. }
  2280. }
  2281. public class UnaryExpression : Expression
  2282. {
  2283. private Expression operand;
  2284. public UnaryExpression()
  2285. : base(NodeType.Nop)
  2286. {
  2287. }
  2288. public UnaryExpression(Expression operand, NodeType nodeType)
  2289. : base(nodeType)
  2290. {
  2291. this.Operand = operand;
  2292. }
  2293. public UnaryExpression(Expression operand, NodeType nodeType, SourceContext sctx)
  2294. : base(nodeType)
  2295. {
  2296. this.operand = operand;
  2297. this.SourceContext = sctx;
  2298. }
  2299. public UnaryExpression(Expression operand, NodeType nodeType, TypeNode type)
  2300. : base(nodeType)
  2301. {
  2302. this.operand = operand;
  2303. this.Type = type;
  2304. }
  2305. public UnaryExpression(Expression operand, NodeType nodeType, TypeNode type, SourceContext sctx)
  2306. : base(nodeType)
  2307. {
  2308. this.operand = operand;
  2309. this.Type = type;
  2310. this.SourceContext = sctx;
  2311. }
  2312. public Expression Operand
  2313. {
  2314. get { return this.operand; }
  2315. set { this.operand = value; }
  2316. }
  2317. }
  2318. public class PrefixExpression : Expression
  2319. {
  2320. public Expression Expression;
  2321. public NodeType Operator;
  2322. public Method OperatorOverload;
  2323. public PrefixExpression()
  2324. : base(NodeType.PrefixExpression)
  2325. {
  2326. }
  2327. public PrefixExpression(Expression expression, NodeType Operator, SourceContext sourceContext)
  2328. : base(NodeType.PrefixExpression)
  2329. {
  2330. this.Expression = expression;
  2331. this.Operator = Operator;
  2332. this.SourceContext = sourceContext;
  2333. }
  2334. }
  2335. public class PostfixExpression : Expression
  2336. {
  2337. public Expression Expression;
  2338. public NodeType Operator;
  2339. public Method OperatorOverload;
  2340. public PostfixExpression()
  2341. : base(NodeType.PostfixExpression)
  2342. {
  2343. }
  2344. public PostfixExpression(Expression expression, NodeType Operator, SourceContext sourceContext)
  2345. : base(NodeType.PostfixExpression)
  2346. {
  2347. this.Expression = expression;
  2348. this.Operator = Operator;
  2349. this.SourceContext = sourceContext;
  2350. }
  2351. }
  2352. public class BinaryExpression : Expression
  2353. {
  2354. private Expression operand1;
  2355. private Expression operand2;
  2356. public BinaryExpression()
  2357. : base(NodeType.Nop)
  2358. {
  2359. }
  2360. public BinaryExpression(Expression operand1, Expression operand2, NodeType nodeType)
  2361. : base(nodeType)
  2362. {
  2363. this.operand1 = operand1;
  2364. this.operand2 = operand2;
  2365. }
  2366. public BinaryExpression(Expression operand1, Expression operand2, NodeType nodeType, TypeNode resultType)
  2367. : base(nodeType)
  2368. {
  2369. this.operand1 = operand1;
  2370. this.operand2 = operand2;
  2371. this.Type = resultType;
  2372. }
  2373. public BinaryExpression(Expression operand1, Expression operand2, NodeType nodeType, SourceContext ctx)
  2374. : base(nodeType)
  2375. {
  2376. this.operand1 = operand1;
  2377. this.operand2 = operand2;
  2378. this.SourceContext = ctx;
  2379. }
  2380. public BinaryExpression(Expression operand1, Expression operand2, NodeType nodeType, TypeNode resultType, SourceContext ctx)
  2381. : base(nodeType)
  2382. {
  2383. this.operand1 = operand1;
  2384. this.operand2 = operand2;
  2385. this.Type = resultType;
  2386. this.SourceContext = ctx;
  2387. }
  2388. public Expression Operand1
  2389. {
  2390. get { return this.operand1; }
  2391. set { this.operand1 = value; }
  2392. }
  2393. public Expression Operand2
  2394. {
  2395. get { return this.operand2; }
  2396. set { this.operand2 = value; }
  2397. }
  2398. }
  2399. public class TernaryExpression : Expression
  2400. {
  2401. private Expression operand1;
  2402. private Expression operand2;
  2403. private Expression operand3;
  2404. public TernaryExpression()
  2405. : base(NodeType.Nop)
  2406. {
  2407. }
  2408. public TernaryExpression(Expression operand1, Expression operand2, Expression operand3, NodeType nodeType, TypeNode resultType)
  2409. : base(nodeType)
  2410. {
  2411. this.operand1 = operand1;
  2412. this.operand2 = operand2;
  2413. this.operand3 = operand3;
  2414. this.Type = resultType;
  2415. }
  2416. public Expression Operand1
  2417. {
  2418. get { return this.operand1; }
  2419. set { this.operand1 = value; }
  2420. }
  2421. public Expression Operand2
  2422. {
  2423. get { return this.operand2; }
  2424. set { this.operand2 = value; }
  2425. }
  2426. public Expression Operand3
  2427. {
  2428. get { return this.operand3; }
  2429. set { this.operand3 = value; }
  2430. }
  2431. }
  2432. public abstract class NaryExpression : Expression
  2433. {
  2434. public ExpressionList Operands;
  2435. protected NaryExpression()
  2436. : base(NodeType.Nop)
  2437. {
  2438. }
  2439. protected NaryExpression(ExpressionList operands, NodeType nodeType)
  2440. : base(nodeType)
  2441. {
  2442. this.Operands = operands;
  2443. }
  2444. }
  2445. public class ApplyToAll : BinaryExpression
  2446. {
  2447. public Local ElementLocal;
  2448. public Method ResultIterator;
  2449. public ApplyToAll()
  2450. : base(null, null, NodeType.ApplyToAll)
  2451. {
  2452. }
  2453. public ApplyToAll(Expression operand1, Expression operand2)
  2454. : base(operand1, operand2, NodeType.ApplyToAll)
  2455. {
  2456. }
  2457. public ApplyToAll(Expression operand1, Expression operand2, SourceContext ctx)
  2458. : base(operand1, operand2, NodeType.ApplyToAll)
  2459. {
  2460. this.SourceContext = ctx;
  2461. }
  2462. }
  2463. public class NamedArgument : Expression
  2464. {
  2465. private bool isCustomAttributeProperty;
  2466. private Identifier name;
  2467. private Expression value;
  2468. private bool valueIsBoxed;
  2469. public NamedArgument()
  2470. : base(NodeType.NamedArgument)
  2471. {
  2472. }
  2473. public NamedArgument(Identifier name, Expression value)
  2474. : base(NodeType.NamedArgument)
  2475. {
  2476. this.Name = name;
  2477. this.Value = value;
  2478. }
  2479. public NamedArgument(Identifier name, Expression value, SourceContext ctx)
  2480. : base(NodeType.NamedArgument)
  2481. {
  2482. this.Name = name;
  2483. this.Value = value;
  2484. this.SourceContext = ctx;
  2485. }
  2486. public bool IsCustomAttributeProperty
  2487. { //TODO: rename this to IsProperty
  2488. get { return this.isCustomAttributeProperty; }
  2489. set { this.isCustomAttributeProperty = value; }
  2490. }
  2491. public Identifier Name
  2492. {
  2493. get { return this.name; }
  2494. set { this.name = value; }
  2495. }
  2496. public Expression Value
  2497. {
  2498. get { return this.value; }
  2499. set { this.value = value; }
  2500. }
  2501. public bool ValueIsBoxed
  2502. {
  2503. get { return this.valueIsBoxed; }
  2504. set { this.valueIsBoxed = value; }
  2505. }
  2506. }
  2507. /// <summary>
  2508. /// This an Expression wrapper for compile time constants. It is assumed to be correct by construction.
  2509. /// In Normalized IR, the wrapped value must be a primitive numeric type or an enum or a string or null.
  2510. /// If used in custom attributes, types are also allowed as well as single dimensional arrays of other allowed types.
  2511. /// If the wrapped value is null, any reference type is allowed, except in custom attributes, where it must be Type or String.
  2512. /// </summary>
  2513. public class Literal : Expression
  2514. {
  2515. private object value;
  2516. public bool TypeWasExplicitlySpecifiedInSource;
  2517. public Expression SourceExpression;
  2518. public Literal()
  2519. : base(NodeType.Literal)
  2520. {
  2521. }
  2522. public Literal(object Value)
  2523. : base(NodeType.Literal)
  2524. {
  2525. this.value = Value;
  2526. }
  2527. public Literal(object value, TypeNode type)
  2528. : base(NodeType.Literal)
  2529. {
  2530. this.value = value;
  2531. this.Type = type;
  2532. }
  2533. public Literal(object value, TypeNode type, SourceContext sourceContext)
  2534. : base(NodeType.Literal)
  2535. {
  2536. this.value = value;
  2537. this.SourceContext = sourceContext;
  2538. this.Type = type;
  2539. }
  2540. /// <summary>
  2541. /// Holds the wrapped compile time constant value.
  2542. /// </summary>
  2543. public object Value
  2544. {
  2545. get { return this.value; }
  2546. }
  2547. public override string ToString()
  2548. {
  2549. if(this.Value == null)
  2550. return "Literal for null";
  2551. return this.Value.ToString();
  2552. }
  2553. }
  2554. public class This : Parameter
  2555. {
  2556. public This()
  2557. {
  2558. this.NodeType = NodeType.This;
  2559. this.Name = StandardIds.This;
  2560. }
  2561. public This(TypeNode type)
  2562. {
  2563. this.NodeType = NodeType.This;
  2564. this.Name = StandardIds.This;
  2565. this.Type = type;
  2566. }
  2567. public bool IsCtorCall = false;
  2568. public This(SourceContext sctx, bool isCtorCall)
  2569. {
  2570. this.NodeType = NodeType.This;
  2571. this.Name = StandardIds.This;
  2572. this.SourceContext = sctx;
  2573. this.IsCtorCall = isCtorCall;
  2574. }
  2575. public This(TypeNode type, SourceContext sctx)
  2576. {
  2577. this.NodeType = NodeType.This;
  2578. this.Name = StandardIds.This;
  2579. this.Type = type;
  2580. this.SourceContext = sctx;
  2581. }
  2582. public override bool Equals(object obj)
  2583. {
  2584. ThisBinding binding = obj as ThisBinding;
  2585. return obj == this || binding != null && binding.BoundThis == this;
  2586. }
  2587. public override int GetHashCode()
  2588. {
  2589. return base.GetHashCode();
  2590. }
  2591. }
  2592. public class ThisBinding : This, IUniqueKey
  2593. {
  2594. public This/*!*/ BoundThis;
  2595. public ThisBinding(This/*!*/ boundThis, SourceContext sctx)
  2596. {
  2597. if(boundThis == null)
  2598. throw new ArgumentNullException("boundThis");
  2599. this.BoundThis = boundThis;
  2600. this.SourceContext = sctx;
  2601. this.Type = boundThis.Type;
  2602. this.Name = boundThis.Name;
  2603. this.TypeExpression = boundThis.TypeExpression;
  2604. this.Attributes = boundThis.Attributes;
  2605. this.DefaultValue = boundThis.DefaultValue;
  2606. this.Flags = boundThis.Flags;
  2607. this.MarshallingInformation = boundThis.MarshallingInformation;
  2608. this.DeclaringMethod = boundThis.DeclaringMethod;
  2609. this.ParameterListIndex = boundThis.ParameterListIndex;
  2610. this.ArgumentListIndex = boundThis.ArgumentListIndex;
  2611. //^ base();
  2612. }
  2613. public override int GetHashCode()
  2614. {
  2615. return this.BoundThis.GetHashCode();
  2616. }
  2617. public override bool Equals(object obj)
  2618. {
  2619. ThisBinding pb = obj as ThisBinding;
  2620. if(pb != null)
  2621. return this.BoundThis.Equals(pb.BoundThis);
  2622. else
  2623. return this.BoundThis.Equals(obj);
  2624. }
  2625. int IUniqueKey.UniqueId
  2626. {
  2627. get { return this.BoundThis.UniqueKey; }
  2628. }
  2629. /// <summary>
  2630. /// Must forward type to underlying binding, since ThisBindings get built at times when
  2631. /// the bound This node does not have its final type yet.
  2632. /// </summary>
  2633. public override TypeNode Type
  2634. {
  2635. get
  2636. {
  2637. return BoundThis.Type;
  2638. }
  2639. set
  2640. {
  2641. BoundThis.Type = value;
  2642. }
  2643. }
  2644. }
  2645. public class Base : Expression
  2646. {
  2647. /// <summary>
  2648. /// When the source uses the C# compatibility mode, base calls cannot be put after non-null
  2649. /// field initialization, but must be put before the body. But the user can specify where
  2650. /// the base ctor call should be performed by using "base;" as a marker. During parsing
  2651. /// this flag is set so the right code transformations can be performed at code generation.
  2652. /// </summary>
  2653. public bool UsedAsMarker;
  2654. public bool IsCtorCall = false;
  2655. public Base()
  2656. : base(NodeType.Base)
  2657. {
  2658. }
  2659. public Base(SourceContext sctx, bool isCtorCall)
  2660. : base(NodeType.Base)
  2661. {
  2662. this.SourceContext = sctx;
  2663. this.IsCtorCall = isCtorCall;
  2664. }
  2665. }
  2666. public class ImplicitThis : Expression
  2667. {
  2668. public int LexLevel;
  2669. public Class MostNestedScope;
  2670. public ImplicitThis()
  2671. : base(NodeType.ImplicitThis)
  2672. {
  2673. }
  2674. public ImplicitThis(Class mostNestedScope, int lexLevel)
  2675. : base(NodeType.ImplicitThis)
  2676. {
  2677. this.LexLevel = lexLevel;
  2678. this.MostNestedScope = mostNestedScope;
  2679. }
  2680. }
  2681. public class CurrentClosure : Expression
  2682. {
  2683. public Method Method;
  2684. public CurrentClosure()
  2685. : base(NodeType.CurrentClosure)
  2686. {
  2687. }
  2688. public CurrentClosure(Method method, TypeNode type)
  2689. : base(NodeType.CurrentClosure)
  2690. {
  2691. this.Method = method;
  2692. this.Type = type;
  2693. }
  2694. public CurrentClosure(Method method, TypeNode type, SourceContext sctx)
  2695. : base(NodeType.CurrentClosure)
  2696. {
  2697. this.Method = method;
  2698. this.Type = type;
  2699. this.SourceContext = sctx;
  2700. }
  2701. }
  2702. public class SetterValue : Expression
  2703. {
  2704. public SetterValue()
  2705. : base(NodeType.SetterValue)
  2706. {
  2707. }
  2708. }
  2709. public class Identifier : Expression
  2710. {
  2711. private int hashCode;
  2712. internal int length;
  2713. private string name;
  2714. private int offset;
  2715. private DocumentText text;
  2716. public Identifier Prefix;
  2717. /// <summary>An identifier with the empty string ("") as its value.</summary>
  2718. public static readonly Identifier/*!*/ Empty = new Identifier("");
  2719. private Identifier(DocumentText/*!*/ text, int offset, int length)
  2720. : base(NodeType.Identifier)
  2721. {
  2722. this.text = text;
  2723. this.offset = offset;
  2724. this.length = length;
  2725. ulong hcode = 0;
  2726. for(int i = offset, n = length + i; i < n; i++)
  2727. {
  2728. char ch = text[i];
  2729. hcode = hcode * 17 + ch;
  2730. }
  2731. this.hashCode = ((int)hcode) & int.MaxValue;
  2732. }
  2733. public static Identifier/*!*/ For(SourceContext sctx)
  2734. {
  2735. DocumentText text = null;
  2736. if(sctx.Document != null)
  2737. text = sctx.Document.Text;
  2738. if(text == null)
  2739. text = new DocumentText("");
  2740. Identifier id = new Identifier(text, sctx.StartPos, sctx.EndPos - sctx.StartPos);
  2741. id.SourceContext = sctx;
  2742. return id;
  2743. }
  2744. public Identifier(string name)
  2745. : base(NodeType.Identifier)
  2746. {
  2747. if(name == null)
  2748. name = "";
  2749. this.name = name;
  2750. int n = this.length = name.Length;
  2751. ulong hcode = 0;
  2752. for(int i = 0; i < n; i++)
  2753. {
  2754. char ch = name[i];
  2755. hcode = hcode * 17 + ch;
  2756. }
  2757. this.hashCode = ((int)hcode) & int.MaxValue;
  2758. }
  2759. public Identifier(string name, SourceContext sctx)
  2760. : this(name)
  2761. {
  2762. this.SourceContext = sctx;
  2763. }
  2764. public static Identifier/*!*/ For(string/*!*/ name)
  2765. {
  2766. return new Identifier(name);
  2767. }
  2768. private unsafe Identifier(byte* pointer, int offset)
  2769. : base(NodeType.Identifier)
  2770. {
  2771. this.offset = offset;
  2772. bool isASCII = true;
  2773. int length = 0;
  2774. ulong hcode = 0;
  2775. for(int i = offset; ; i++)
  2776. {
  2777. byte b = *(pointer + i);
  2778. if(b == 0)
  2779. break;
  2780. if((b & 0x80) != 0)
  2781. isASCII = false;
  2782. hcode = hcode * 17 + b;
  2783. length++;
  2784. }
  2785. if(isASCII)
  2786. {
  2787. this.hashCode = ((int)hcode) & int.MaxValue;
  2788. this.length = length;
  2789. this.name = new string((sbyte*)pointer, offset, length, Encoding.ASCII);
  2790. return;
  2791. }
  2792. hcode = 0;
  2793. string name = this.name = new string((sbyte*)pointer, offset, length, Encoding.UTF8);
  2794. for(int i = 0, n = this.length = name.Length; i < n; i++)
  2795. {
  2796. char ch = name[i];
  2797. hcode = hcode * 17 + ch;
  2798. }
  2799. this.hashCode = ((int)hcode) & int.MaxValue;
  2800. }
  2801. /// <summary>
  2802. /// Use when pointer+offset points to a null terminated string of UTF8 code points.
  2803. /// </summary>
  2804. internal unsafe static Identifier/*!*/ For(byte* pointer, int offset)
  2805. {
  2806. //TODO: first look for identifier in cache
  2807. return new Identifier(pointer, offset);
  2808. }
  2809. private unsafe Identifier(byte* pointer, uint length)
  2810. : base(NodeType.Identifier)
  2811. {
  2812. //this.offset = 0;
  2813. this.length = (int)length;
  2814. ulong hcode = 0;
  2815. for(uint i = 0; i < length; i++)
  2816. {
  2817. byte b = *(pointer + i);
  2818. if((b & 0x80) != 0)
  2819. goto doUTF8decoding;
  2820. hcode = hcode * 17 + b;
  2821. }
  2822. this.hashCode = ((int)hcode) & int.MaxValue;
  2823. this.name = new string((sbyte*)pointer, 0, this.length, Encoding.ASCII);
  2824. return;
  2825. doUTF8decoding:
  2826. string name = this.name = new string((sbyte*)pointer, 0, this.length, Encoding.UTF8);
  2827. for(int i = 0, n = this.length = name.Length; i < n; i++)
  2828. {
  2829. char ch = name[i];
  2830. hcode = hcode * 17 + ch;
  2831. }
  2832. this.hashCode = ((int)hcode) & int.MaxValue;
  2833. }
  2834. /// <summary>
  2835. /// Use when pointer points to a string of UTF8 code points of a given length
  2836. /// </summary>
  2837. internal unsafe static Identifier/*!*/ For(byte* pointer, uint length)
  2838. {
  2839. //TODO: first look for identifier in cache
  2840. return new Identifier(pointer, length);
  2841. }
  2842. private static readonly object/*!*/ Lock = new object();
  2843. private struct CanonicalIdentifier
  2844. {
  2845. internal string/*!*/ Name;
  2846. internal int UniqueIdKey;
  2847. internal int HashCode;
  2848. internal CanonicalIdentifier(string/*!*/ name, int uniqueIdKey, int hashCode)
  2849. {
  2850. this.Name = name;
  2851. this.UniqueIdKey = uniqueIdKey;
  2852. this.HashCode = hashCode;
  2853. }
  2854. }
  2855. private static CanonicalIdentifier[]/*!*/ HashTable = new CanonicalIdentifier[16 * 1024];
  2856. private static int count;
  2857. private int GetUniqueIdKey()
  2858. {
  2859. lock(Identifier.Lock)
  2860. {
  2861. int hcode = this.hashCode;
  2862. CanonicalIdentifier[] hTable = Identifier.HashTable;
  2863. int length = hTable.Length;
  2864. int i = hcode % length;
  2865. CanonicalIdentifier id = hTable[i];
  2866. while(id.Name != null)
  2867. {
  2868. if(this.HasSameNameAs(id))
  2869. return id.UniqueIdKey;
  2870. i = (i + 1) % length;
  2871. id = hTable[i];
  2872. }
  2873. int count = Identifier.count;
  2874. int countp1 = count + 1;
  2875. Identifier.count = countp1;
  2876. string name = this.Name; //Get a local copy of the name and drop any reference to a DocumentText instance
  2877. hTable[i] = new CanonicalIdentifier(name, countp1, hcode);
  2878. if(countp1 > length / 2)
  2879. Rehash(); //Threshold exceeded, need to rehash
  2880. return countp1;
  2881. }
  2882. }
  2883. private unsafe bool HasSameNameAs(CanonicalIdentifier id)
  2884. {
  2885. int myLength = this.length;
  2886. int idLength = id.Name.Length;
  2887. if(myLength != idLength)
  2888. return false;
  2889. string myName = this.name;
  2890. string idName = id.Name;
  2891. if(myName == null)
  2892. {
  2893. int myOffset = this.offset;
  2894. if(this.text != null && this.text.Equals(idName, myOffset, myLength))
  2895. {
  2896. this.name = idName;
  2897. this.text = null;
  2898. return true;
  2899. }
  2900. return false;
  2901. }
  2902. return myName == idName;
  2903. }
  2904. public string/*!*/ Name
  2905. { //TODO: need a better name for this property
  2906. get
  2907. {
  2908. if(this.name != null)
  2909. return this.name;
  2910. lock(this)
  2911. {
  2912. if(this.name != null)
  2913. return this.name;
  2914. //^ assume this.text != null;
  2915. int length = this.length;
  2916. int offset = this.offset;
  2917. this.name = this.text.Substring(offset, length);
  2918. this.text = null;
  2919. return this.name;
  2920. }
  2921. }
  2922. }
  2923. private static void Rehash()
  2924. {
  2925. CanonicalIdentifier[] hTable = Identifier.HashTable;
  2926. int n = hTable.Length;
  2927. int n2 = n * 2;
  2928. CanonicalIdentifier[] newhTable = new CanonicalIdentifier[n2];
  2929. for(int i = 0; i < n; i++)
  2930. {
  2931. CanonicalIdentifier id = hTable[i];
  2932. if(id.Name == null)
  2933. continue;
  2934. int j = id.HashCode % n2;
  2935. CanonicalIdentifier id2 = newhTable[j];
  2936. while(id2.Name != null)
  2937. {
  2938. j = (j + 1) % n2;
  2939. id2 = newhTable[j];
  2940. }
  2941. newhTable[j] = id;
  2942. }
  2943. Identifier.HashTable = newhTable;
  2944. }
  2945. public override string/*!*/ ToString()
  2946. {
  2947. if(this.Prefix != null)
  2948. return this.Prefix.Name + ":" + this.Name;
  2949. if(this.Name == null)
  2950. return "";
  2951. return this.Name;
  2952. }
  2953. private int uniqueIdKey;
  2954. /// <summary>
  2955. /// Returns an integer that is the same for every Identifier instance that has the same string value, and that is different from
  2956. /// every other identifier instance that has a different string value. Useful for efficient equality tests when hashing identifiers.
  2957. /// </summary>
  2958. public int UniqueIdKey
  2959. {
  2960. get
  2961. {
  2962. int result = this.uniqueIdKey;
  2963. if(result != 0)
  2964. return result;
  2965. return this.uniqueIdKey = this.GetUniqueIdKey();
  2966. }
  2967. }
  2968. [Obsolete("Use Identifier.UniqueIdKey instead")]
  2969. public new int UniqueKey
  2970. {
  2971. get
  2972. {
  2973. int result = this.uniqueIdKey;
  2974. if(result != 0)
  2975. return result;
  2976. return this.uniqueIdKey = this.GetUniqueIdKey();
  2977. }
  2978. }
  2979. }
  2980. public class QualifiedIdentifier : Expression
  2981. {
  2982. public Identifier Identifier;
  2983. public Expression Qualifier;
  2984. public Expression BoundMember;
  2985. public bool QualifierIsNamespace;
  2986. public QualifiedIdentifier()
  2987. : base(NodeType.QualifiedIdentifer)
  2988. {
  2989. }
  2990. public QualifiedIdentifier(Expression qualifier, Identifier identifier)
  2991. : base(NodeType.QualifiedIdentifer)
  2992. {
  2993. this.Identifier = identifier;
  2994. this.Qualifier = qualifier;
  2995. }
  2996. public QualifiedIdentifier(Expression qualifier, Identifier identifier, SourceContext sourceContext)
  2997. : base(NodeType.QualifiedIdentifer)
  2998. {
  2999. this.Identifier = identifier;
  3000. this.Qualifier = qualifier;
  3001. this.SourceContext = sourceContext;
  3002. }
  3003. public QualifiedIdentifier(Expression qualifier, Identifier identifier, SourceContext sourceContext, bool qualifierIsNamespace)
  3004. : base(NodeType.QualifiedIdentifer)
  3005. {
  3006. this.Identifier = identifier;
  3007. this.Qualifier = qualifier;
  3008. this.SourceContext = sourceContext;
  3009. this.QualifierIsNamespace = qualifierIsNamespace;
  3010. }
  3011. public override string/*!*/ ToString()
  3012. {
  3013. string str = this.Identifier == null ? "" : this.Identifier.ToString();
  3014. if(this.Qualifier == null)
  3015. return str;
  3016. string separator = this.QualifierIsNamespace ? "::" : "+";
  3017. return this.Qualifier.ToString() + separator + str;
  3018. }
  3019. }
  3020. public class Quantifier : Expression
  3021. {
  3022. public NodeType QuantifierType;
  3023. public TypeNode SourceType; // the type of elements the quantifier consumes
  3024. public Comprehension Comprehension;
  3025. public Quantifier()
  3026. : base(NodeType.Quantifier)
  3027. {
  3028. }
  3029. public Quantifier(Comprehension comprehension)
  3030. : base(NodeType.Quantifier)
  3031. {
  3032. this.Comprehension = comprehension;
  3033. }
  3034. public Quantifier(NodeType t, Comprehension comprehension)
  3035. : base(NodeType.Quantifier)
  3036. {
  3037. this.QuantifierType = t;
  3038. this.Comprehension = comprehension;
  3039. }
  3040. }
  3041. public enum ComprehensionBindingMode { In, Gets };
  3042. public class ComprehensionBinding : Expression
  3043. {
  3044. public ComprehensionBindingMode Mode = ComprehensionBindingMode.In;
  3045. public TypeNode TargetVariableType;
  3046. public TypeNode TargetVariableTypeExpression;
  3047. public Expression TargetVariable;
  3048. public TypeNode AsTargetVariableType;
  3049. public TypeNode AsTargetVariableTypeExpression;
  3050. public Expression SourceEnumerable;
  3051. public BlockScope ScopeForTemporaryVariables;
  3052. public ComprehensionBinding()
  3053. : base(NodeType.ComprehensionBinding)
  3054. {
  3055. }
  3056. }
  3057. public enum ComprehensionMode { Reduction, Comprehension };
  3058. // {1,2,3} ==> Comprehension with BindingsAndFilters = null and Elements = [1,2,3]
  3059. // i.e., for a "display", there are no bindings and the elements have one entry per value in the comprehension
  3060. // { int x in A, P(x); T(x); default } ==> Comprehension with BindingsAndFilters = [int x in A, P(x)] and Elements = [T(x), default]
  3061. // i.e., for "true" comprehensions, the list of elements will always have either one or two elements (two if there is a default)
  3062. public class Comprehension : Expression
  3063. {
  3064. public ComprehensionMode Mode = ComprehensionMode.Comprehension;
  3065. public ExpressionList BindingsAndFilters;
  3066. public ExpressionList Elements;
  3067. public Node nonEnumerableTypeCtor; // used only when the comprehension should generate code for an IList, e.g.
  3068. public Method AddMethod; // used only when the comprehension should generate code for an IList, e.g.
  3069. public TypeNode TemporaryHackToHoldType;
  3070. public Comprehension()
  3071. : base(NodeType.Comprehension)
  3072. {
  3073. }
  3074. public bool IsDisplay
  3075. {
  3076. get
  3077. {
  3078. return this.BindingsAndFilters == null;
  3079. }
  3080. }
  3081. }
  3082. public class NameBinding : Expression
  3083. {
  3084. public Identifier Identifier;
  3085. public MemberList BoundMembers;
  3086. public Expression BoundMember;
  3087. public int LexLevel;
  3088. public Class MostNestedScope;
  3089. public NameBinding()
  3090. : base(NodeType.NameBinding)
  3091. {
  3092. }
  3093. public NameBinding(Identifier identifier, MemberList boundMembers)
  3094. : base(NodeType.NameBinding)
  3095. {
  3096. this.Identifier = identifier;
  3097. this.BoundMembers = boundMembers;
  3098. }
  3099. public NameBinding(Identifier identifier, MemberList boundMembers, SourceContext sctx)
  3100. : base(NodeType.NameBinding)
  3101. {
  3102. this.Identifier = identifier;
  3103. this.BoundMembers = boundMembers;
  3104. this.SourceContext = sctx;
  3105. }
  3106. public NameBinding(Identifier identifier, MemberList boundMembers, Class mostNestedScope, int lexLevel)
  3107. : base(NodeType.NameBinding)
  3108. {
  3109. this.Identifier = identifier;
  3110. this.BoundMembers = boundMembers;
  3111. this.LexLevel = lexLevel;
  3112. this.MostNestedScope = mostNestedScope;
  3113. }
  3114. public NameBinding(Identifier identifier, MemberList boundMembers, Class mostNestedScope, int lexLevel, SourceContext sctx)
  3115. : base(NodeType.NameBinding)
  3116. {
  3117. this.Identifier = identifier;
  3118. this.BoundMembers = boundMembers;
  3119. this.LexLevel = lexLevel;
  3120. this.MostNestedScope = mostNestedScope;
  3121. this.SourceContext = sctx;
  3122. }
  3123. public override string ToString()
  3124. {
  3125. return this.Identifier == null ? "" : this.Identifier.ToString();
  3126. }
  3127. }
  3128. public class TemplateInstance : Expression
  3129. {
  3130. public Expression Expression;
  3131. public TypeNodeList TypeArguments;
  3132. public TypeNodeList TypeArgumentExpressions;
  3133. public bool IsMethodTemplate;
  3134. public MemberList BoundMembers;
  3135. public TemplateInstance()
  3136. : this(null, null)
  3137. {
  3138. }
  3139. public TemplateInstance(Expression expression, TypeNodeList typeArguments)
  3140. : base(NodeType.TemplateInstance)
  3141. {
  3142. this.Expression = expression;
  3143. this.TypeArguments = typeArguments;
  3144. }
  3145. }
  3146. public class StackAlloc : Expression
  3147. {
  3148. public TypeNode ElementType;
  3149. public TypeNode ElementTypeExpression;
  3150. public Expression NumberOfElements;
  3151. public StackAlloc()
  3152. : base(NodeType.StackAlloc)
  3153. {
  3154. }
  3155. public StackAlloc(TypeNode elementType, Expression numberOfElements, SourceContext sctx)
  3156. : base(NodeType.StackAlloc)
  3157. {
  3158. this.ElementType = this.ElementTypeExpression = elementType;
  3159. this.NumberOfElements = numberOfElements;
  3160. this.SourceContext = sctx;
  3161. }
  3162. }
  3163. public class MethodCall : NaryExpression
  3164. {
  3165. private Expression callee;
  3166. private TypeNode constraint;
  3167. private bool isTailCall;
  3168. public Expression CalleeExpression;
  3169. public bool GiveErrorIfSpecialNameMethod;
  3170. public bool ArgumentListIsIncomplete;
  3171. public MethodCall()
  3172. {
  3173. this.NodeType = NodeType.MethodCall;
  3174. }
  3175. public MethodCall(Expression callee, ExpressionList arguments)
  3176. : base(arguments, NodeType.MethodCall)
  3177. {
  3178. this.callee = this.CalleeExpression = callee;
  3179. this.isTailCall = false;
  3180. }
  3181. public MethodCall(Expression callee, ExpressionList arguments, NodeType typeOfCall)
  3182. : base(arguments, typeOfCall)
  3183. {
  3184. this.callee = callee;
  3185. this.CalleeExpression = callee;
  3186. //this.isTailCall = false;
  3187. }
  3188. public MethodCall(Expression callee, ExpressionList arguments, NodeType typeOfCall, TypeNode resultType)
  3189. : this(callee, arguments, typeOfCall)
  3190. {
  3191. this.Type = resultType;
  3192. }
  3193. public MethodCall(Expression callee, ExpressionList arguments, NodeType typeOfCall, TypeNode resultType, SourceContext sctx)
  3194. : this(callee, arguments, typeOfCall, resultType)
  3195. {
  3196. this.SourceContext = sctx;
  3197. }
  3198. public Expression Callee
  3199. {
  3200. get { return this.callee; }
  3201. set { this.callee = value; }
  3202. }
  3203. public bool IsTailCall
  3204. {
  3205. get { return this.isTailCall; }
  3206. set { this.isTailCall = value; }
  3207. }
  3208. public TypeNode Constraint
  3209. {
  3210. get { return this.constraint; }
  3211. set { this.constraint = value; }
  3212. }
  3213. }
  3214. public class Construct : NaryExpression
  3215. {
  3216. private Expression constructor;
  3217. public Expression Owner;
  3218. public Construct()
  3219. {
  3220. this.NodeType = NodeType.Construct;
  3221. }
  3222. public Construct(Expression constructor, ExpressionList arguments)
  3223. : base(arguments, NodeType.Construct)
  3224. {
  3225. this.constructor = constructor;
  3226. }
  3227. public Construct(Expression constructor, ExpressionList arguments, SourceContext sctx)
  3228. : base(arguments, NodeType.Construct)
  3229. {
  3230. this.constructor = constructor;
  3231. this.SourceContext = sctx;
  3232. }
  3233. public Construct(Expression constructor, ExpressionList arguments, TypeNode type)
  3234. : base(arguments, NodeType.Construct)
  3235. {
  3236. this.constructor = constructor;
  3237. this.Type = type;
  3238. }
  3239. public Construct(Expression constructor, ExpressionList arguments, TypeNode type, SourceContext sctx)
  3240. : base(arguments, NodeType.Construct)
  3241. {
  3242. this.constructor = constructor;
  3243. this.Type = type;
  3244. this.SourceContext = sctx;
  3245. }
  3246. public Expression Constructor
  3247. {
  3248. get { return this.constructor; }
  3249. set { this.constructor = value; }
  3250. }
  3251. }
  3252. public class ConstructArray : NaryExpression
  3253. {
  3254. private TypeNode elementType;
  3255. private int rank;
  3256. public TypeNode ElementTypeExpression;
  3257. public ExpressionList Initializers;
  3258. public Expression Owner;
  3259. public ConstructArray()
  3260. {
  3261. this.NodeType = NodeType.ConstructArray;
  3262. this.rank = 1;
  3263. }
  3264. public ConstructArray(TypeNode elementType, ExpressionList sizes, ExpressionList initializers)
  3265. : base(sizes, NodeType.ConstructArray)
  3266. {
  3267. this.elementType = elementType;
  3268. this.Operands = sizes;
  3269. this.rank = sizes == null ? 1 : sizes.Count;
  3270. this.Initializers = initializers;
  3271. }
  3272. public ConstructArray(TypeNode elementType, ExpressionList initializers)
  3273. : base(null, NodeType.ConstructArray)
  3274. {
  3275. this.elementType = elementType;
  3276. this.Initializers = initializers;
  3277. this.rank = 1;
  3278. if(elementType != null)
  3279. this.Type = elementType.GetArrayType(1);
  3280. }
  3281. public ConstructArray(TypeNode elementType, int rank, ExpressionList initializers)
  3282. : base(null, NodeType.ConstructArray)
  3283. {
  3284. this.elementType = elementType;
  3285. this.Initializers = initializers;
  3286. this.rank = rank;
  3287. if(elementType != null)
  3288. this.Type = elementType.GetArrayType(1);
  3289. }
  3290. public TypeNode ElementType
  3291. {
  3292. get { return this.elementType; }
  3293. set { this.elementType = value; }
  3294. }
  3295. public int Rank
  3296. {
  3297. get { return this.rank; }
  3298. set { this.rank = value; }
  3299. }
  3300. }
  3301. public class ConstructFlexArray : NaryExpression
  3302. {
  3303. public TypeNode ElementType;
  3304. public TypeNode ElementTypeExpression;
  3305. public ExpressionList Initializers;
  3306. public ConstructFlexArray()
  3307. {
  3308. this.NodeType = NodeType.ConstructFlexArray;
  3309. }
  3310. public ConstructFlexArray(TypeNode elementType, ExpressionList sizes, ExpressionList initializers)
  3311. : base(sizes, NodeType.ConstructFlexArray)
  3312. {
  3313. this.ElementType = elementType;
  3314. this.Operands = sizes;
  3315. this.Initializers = initializers;
  3316. }
  3317. }
  3318. public class ConstructDelegate : Expression
  3319. {
  3320. public TypeNode DelegateType;
  3321. public TypeNode DelegateTypeExpression;
  3322. public Identifier MethodName;
  3323. public Expression TargetObject;
  3324. public ConstructDelegate()
  3325. : base(NodeType.ConstructDelegate)
  3326. {
  3327. }
  3328. public ConstructDelegate(TypeNode delegateType, Expression targetObject, Identifier methodName)
  3329. : base(NodeType.ConstructDelegate)
  3330. {
  3331. this.DelegateType = delegateType;
  3332. this.MethodName = methodName;
  3333. this.TargetObject = targetObject;
  3334. }
  3335. public ConstructDelegate(TypeNode delegateType, Expression targetObject, Identifier methodName, SourceContext sctx)
  3336. : base(NodeType.ConstructDelegate)
  3337. {
  3338. this.DelegateType = delegateType;
  3339. this.MethodName = methodName;
  3340. this.TargetObject = targetObject;
  3341. this.SourceContext = sctx;
  3342. }
  3343. }
  3344. public class ConstructIterator : Expression
  3345. {
  3346. public Class State;
  3347. public Block Body;
  3348. public TypeNode ElementType;
  3349. public ConstructIterator()
  3350. : base(NodeType.ConstructIterator)
  3351. {
  3352. }
  3353. public ConstructIterator(Class state, Block body, TypeNode elementType, TypeNode type)
  3354. : base(NodeType.ConstructIterator)
  3355. {
  3356. this.State = state;
  3357. this.Body = body;
  3358. this.ElementType = elementType;
  3359. this.Type = type;
  3360. }
  3361. }
  3362. public class ConstructTuple : Expression
  3363. {
  3364. public FieldList Fields;
  3365. public ConstructTuple()
  3366. : base(NodeType.ConstructTuple)
  3367. {
  3368. }
  3369. }
  3370. public class CoerceTuple : ConstructTuple
  3371. {
  3372. public Expression OriginalTuple;
  3373. public Local Temp;
  3374. public CoerceTuple()
  3375. {
  3376. this.NodeType = NodeType.CoerceTuple;
  3377. }
  3378. }
  3379. public class Indexer : NaryExpression
  3380. {
  3381. public Property CorrespondingDefaultIndexedProperty;
  3382. public bool ArgumentListIsIncomplete;
  3383. public Indexer()
  3384. {
  3385. this.NodeType = NodeType.Indexer;
  3386. }
  3387. public Indexer(Expression @object, ExpressionList arguments)
  3388. : base(arguments, NodeType.Indexer)
  3389. {
  3390. this.@object = @object;
  3391. }
  3392. public Indexer(Expression Object, ExpressionList arguments, SourceContext sctx)
  3393. : base(arguments, NodeType.Indexer)
  3394. {
  3395. this.@object = Object;
  3396. this.SourceContext = sctx;
  3397. }
  3398. public Indexer(Expression Object, ExpressionList arguments, TypeNode elementType)
  3399. : base(arguments, NodeType.Indexer)
  3400. {
  3401. this.@object = Object;
  3402. this.elementType = this.Type = elementType;
  3403. }
  3404. public Indexer(Expression Object, ExpressionList arguments, TypeNode elementType, SourceContext sctx)
  3405. : base(arguments, NodeType.Indexer)
  3406. {
  3407. this.@object = Object;
  3408. this.elementType = this.Type = elementType;
  3409. this.SourceContext = sctx;
  3410. }
  3411. private Expression @object;
  3412. public Expression Object
  3413. {
  3414. get { return this.@object; }
  3415. set { this.@object = value; }
  3416. }
  3417. private TypeNode elementType;
  3418. /// <summary>
  3419. /// This type is normally expected to be the same the value of Type. However, if the indexer applies to an array of enums, then
  3420. /// Type will be the enum type and ElementType will be the underlying type of the enum.
  3421. /// </summary>
  3422. public TypeNode ElementType
  3423. {
  3424. get { return this.elementType; }
  3425. set { this.elementType = value; }
  3426. }
  3427. }
  3428. public class CollectionEnumerator : Expression
  3429. {
  3430. public Expression Collection;
  3431. public Method DefaultIndexerGetter;
  3432. public Method LengthPropertyGetter;
  3433. public Method GetEnumerator;
  3434. public Method MoveNext;
  3435. public Method GetCurrent;
  3436. public Local ElementLocal;
  3437. public Expression ElementCoercion;
  3438. public CollectionEnumerator()
  3439. : base(NodeType.CollectionEnumerator)
  3440. {
  3441. }
  3442. }
  3443. /// <summary>
  3444. /// 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).
  3445. /// </summary>
  3446. public class LRExpression : Expression
  3447. {
  3448. public Expression Expression;
  3449. public LRExpression(Expression/*!*/ expression) : base(NodeType.LRExpression)
  3450. {
  3451. this.Expression = expression;
  3452. this.Type = expression.Type;
  3453. }
  3454. }
  3455. public class AssignmentExpression : Expression
  3456. {
  3457. public Statement AssignmentStatement;
  3458. public AssignmentExpression()
  3459. : base(NodeType.AssignmentExpression)
  3460. {
  3461. }
  3462. public AssignmentExpression(AssignmentStatement assignment)
  3463. : base(NodeType.AssignmentExpression)
  3464. {
  3465. this.AssignmentStatement = assignment;
  3466. }
  3467. }
  3468. public class BlockExpression : Expression
  3469. {
  3470. public Block Block;
  3471. public BlockExpression()
  3472. : base(NodeType.BlockExpression)
  3473. {
  3474. }
  3475. public BlockExpression(Block block)
  3476. : base(NodeType.BlockExpression)
  3477. {
  3478. this.Block = block;
  3479. }
  3480. public BlockExpression(Block block, TypeNode type)
  3481. : base(NodeType.BlockExpression)
  3482. {
  3483. this.Block = block;
  3484. this.Type = type;
  3485. }
  3486. public BlockExpression(Block block, TypeNode type, SourceContext sctx)
  3487. : base(NodeType.BlockExpression)
  3488. {
  3489. this.Block = block;
  3490. this.Type = type;
  3491. this.SourceContext = sctx;
  3492. }
  3493. }
  3494. public class AnonymousNestedFunction : Expression
  3495. {
  3496. public ParameterList Parameters;
  3497. public Block Body;
  3498. public Method Method;
  3499. public Expression Invocation;
  3500. public AnonymousNestedFunction()
  3501. : base(NodeType.AnonymousNestedFunction)
  3502. {
  3503. }
  3504. public AnonymousNestedFunction(ParameterList parameters, Block body)
  3505. : base(NodeType.AnonymousNestedFunction)
  3506. {
  3507. this.Parameters = parameters;
  3508. this.Body = body;
  3509. }
  3510. public AnonymousNestedFunction(ParameterList parameters, Block body, SourceContext sctx)
  3511. : base(NodeType.AnonymousNestedFunction)
  3512. {
  3513. this.Parameters = parameters;
  3514. this.Body = body;
  3515. this.SourceContext = sctx;
  3516. }
  3517. }
  3518. public class Instruction : Node
  3519. {
  3520. private OpCode opCode;
  3521. private int offset;
  3522. private object value;
  3523. public Instruction()
  3524. : base(NodeType.Instruction)
  3525. {
  3526. }
  3527. public Instruction(OpCode opCode, int offset)
  3528. : this(opCode, offset, null)
  3529. {
  3530. }
  3531. public Instruction(OpCode opCode, int offset, object value)
  3532. : base(NodeType.Instruction)
  3533. {
  3534. this.opCode = opCode;
  3535. this.offset = offset;
  3536. this.value = value;
  3537. }
  3538. /// <summary>The actual value of the opcode</summary>
  3539. public OpCode OpCode
  3540. {
  3541. get { return this.opCode; }
  3542. set { this.opCode = value; }
  3543. }
  3544. /// <summary>The offset from the start of the instruction stream of a method</summary>
  3545. public int Offset
  3546. {
  3547. get { return this.offset; }
  3548. set { this.offset = value; }
  3549. }
  3550. /// <summary>Immediate data such as a string, the address of a branch target, or a metadata reference, such as a Field</summary>
  3551. public object Value
  3552. {
  3553. get { return this.value; }
  3554. set { this.value = value; }
  3555. }
  3556. }
  3557. public class Statement : Node
  3558. {
  3559. public Statement(NodeType nodeType)
  3560. : base(nodeType)
  3561. {
  3562. }
  3563. public Statement(NodeType nodeType, SourceContext sctx)
  3564. : base(nodeType)
  3565. {
  3566. this.SourceContext = sctx;
  3567. }
  3568. }
  3569. public class Block : Statement
  3570. {
  3571. private StatementList statements;
  3572. public bool Checked;
  3573. public bool SuppressCheck;
  3574. public bool HasLocals;
  3575. public bool IsUnsafe;
  3576. public BlockScope Scope;
  3577. public Block()
  3578. : base(NodeType.Block)
  3579. {
  3580. }
  3581. public Block(StatementList statements)
  3582. : base(NodeType.Block)
  3583. {
  3584. this.statements = statements;
  3585. }
  3586. public Block(StatementList statements, SourceContext sourceContext)
  3587. : base(NodeType.Block)
  3588. {
  3589. this.SourceContext = sourceContext;
  3590. this.statements = statements;
  3591. }
  3592. public Block(StatementList statements, bool Checked, bool SuppressCheck, bool IsUnsafe)
  3593. : base(NodeType.Block)
  3594. {
  3595. this.Checked = Checked;
  3596. this.IsUnsafe = IsUnsafe;
  3597. this.SuppressCheck = SuppressCheck;
  3598. this.statements = statements;
  3599. }
  3600. public Block(StatementList statements, SourceContext sourceContext, bool Checked, bool SuppressCheck, bool IsUnsafe)
  3601. : base(NodeType.Block)
  3602. {
  3603. this.Checked = Checked;
  3604. this.IsUnsafe = IsUnsafe;
  3605. this.SuppressCheck = SuppressCheck;
  3606. this.SourceContext = sourceContext;
  3607. this.statements = statements;
  3608. }
  3609. public override string ToString()
  3610. {
  3611. return "B#" + this.UniqueKey.ToString();
  3612. }
  3613. public StatementList Statements
  3614. {
  3615. get { return this.statements; }
  3616. set { this.statements = value; }
  3617. }
  3618. }
  3619. public class LabeledStatement : Block
  3620. {
  3621. public Identifier Label;
  3622. public Statement Statement;
  3623. public LabeledStatement()
  3624. {
  3625. this.NodeType = NodeType.LabeledStatement;
  3626. }
  3627. }
  3628. public class FunctionDeclaration : Statement
  3629. {
  3630. public Identifier Name;
  3631. public ParameterList Parameters;
  3632. public TypeNode ReturnType;
  3633. public TypeNode ReturnTypeExpression;
  3634. public Block Body;
  3635. public Method Method;
  3636. public FunctionDeclaration()
  3637. : base(NodeType.FunctionDeclaration)
  3638. {
  3639. }
  3640. public FunctionDeclaration(Identifier name, ParameterList parameters, TypeNode returnType, Block body)
  3641. : base(NodeType.FunctionDeclaration)
  3642. {
  3643. this.Name = name;
  3644. this.Parameters = parameters;
  3645. this.ReturnType = returnType;
  3646. this.Body = body;
  3647. }
  3648. }
  3649. public class Assertion : Statement
  3650. {
  3651. public Expression Condition;
  3652. public Assertion()
  3653. : base(NodeType.Assertion)
  3654. {
  3655. }
  3656. public Assertion(Expression condition)
  3657. : base(NodeType.Assertion)
  3658. {
  3659. this.Condition = condition;
  3660. }
  3661. }
  3662. public class Assumption : Statement
  3663. {
  3664. public Expression Condition;
  3665. public Assumption()
  3666. : base(NodeType.Assumption)
  3667. {
  3668. }
  3669. public Assumption(Expression condition)
  3670. : base(NodeType.Assumption)
  3671. {
  3672. this.Condition = condition;
  3673. }
  3674. }
  3675. public class AssignmentStatement : Statement
  3676. {
  3677. private NodeType @operator;
  3678. private Expression source;
  3679. private Expression target;
  3680. public Method OperatorOverload;
  3681. ///<summary>A Type two which both operands must be coerced before carrying out the operation (if any).</summary>
  3682. public TypeNode UnifiedType;
  3683. public AssignmentStatement()
  3684. : base(NodeType.AssignmentStatement)
  3685. {
  3686. this.Operator = NodeType.Nop;
  3687. }
  3688. public AssignmentStatement(Expression target, Expression source)
  3689. : this(target, source, NodeType.Nop)
  3690. {
  3691. }
  3692. public AssignmentStatement(Expression target, Expression source, SourceContext context)
  3693. : this(target, source, NodeType.Nop)
  3694. {
  3695. this.SourceContext = context;
  3696. }
  3697. public AssignmentStatement(Expression target, Expression source, NodeType @operator)
  3698. : base(NodeType.AssignmentStatement)
  3699. {
  3700. this.target = target;
  3701. this.source = source;
  3702. this.@operator = @operator;
  3703. }
  3704. public AssignmentStatement(Expression target, Expression source, NodeType Operator, SourceContext context)
  3705. : this(target, source, Operator)
  3706. {
  3707. this.SourceContext = context;
  3708. }
  3709. public NodeType Operator
  3710. {
  3711. get { return this.@operator; }
  3712. set { this.@operator = value; }
  3713. }
  3714. public Expression Source
  3715. {
  3716. get { return this.source; }
  3717. set { this.source = value; }
  3718. }
  3719. public Expression Target
  3720. {
  3721. get { return this.target; }
  3722. set { this.target = value; }
  3723. }
  3724. }
  3725. public class ExpressionStatement : Statement
  3726. {
  3727. private Expression expression;
  3728. public ExpressionStatement()
  3729. : base(NodeType.ExpressionStatement)
  3730. {
  3731. }
  3732. public ExpressionStatement(Expression expression)
  3733. : base(NodeType.ExpressionStatement)
  3734. {
  3735. this.Expression = expression;
  3736. }
  3737. public ExpressionStatement(Expression expression, SourceContext sctx)
  3738. : base(NodeType.ExpressionStatement)
  3739. {
  3740. this.Expression = expression;
  3741. this.SourceContext = sctx;
  3742. }
  3743. public Expression Expression
  3744. {
  3745. get { return this.expression; }
  3746. set { this.expression = value; }
  3747. }
  3748. }
  3749. public class Branch : Statement
  3750. {
  3751. private Expression condition;
  3752. private bool leavesExceptionBlock;
  3753. internal bool shortOffset;
  3754. private Block target;
  3755. public bool BranchIfUnordered;
  3756. public Branch()
  3757. : base(NodeType.Branch)
  3758. {
  3759. }
  3760. public Branch(Expression condition, Block target)
  3761. : this(condition, target, false, false, false)
  3762. {
  3763. }
  3764. public Branch(Expression condition, Block target, SourceContext sourceContext)
  3765. : this(condition, target, false, false, false)
  3766. {
  3767. this.SourceContext = sourceContext;
  3768. }
  3769. public Branch(Expression condition, Block target, SourceContext sourceContext, bool unordered)
  3770. : this(condition, target, false, false, false)
  3771. {
  3772. this.BranchIfUnordered = unordered;
  3773. this.SourceContext = sourceContext;
  3774. }
  3775. public Branch(Expression condition, Block target, bool shortOffset, bool unordered, bool leavesExceptionBlock)
  3776. : base(NodeType.Branch)
  3777. {
  3778. this.BranchIfUnordered = unordered;
  3779. this.condition = condition;
  3780. this.leavesExceptionBlock = leavesExceptionBlock;
  3781. this.shortOffset = shortOffset;
  3782. this.target = target;
  3783. }
  3784. public Expression Condition
  3785. {
  3786. get { return this.condition; }
  3787. set { this.condition = value; }
  3788. }
  3789. public bool LeavesExceptionBlock
  3790. {
  3791. get { return this.leavesExceptionBlock; }
  3792. set { this.leavesExceptionBlock = value; }
  3793. }
  3794. public bool ShortOffset
  3795. {
  3796. get { return this.shortOffset; }
  3797. set { this.shortOffset = value; }
  3798. }
  3799. public Block Target
  3800. {
  3801. get { return this.target; }
  3802. set { this.target = value; }
  3803. }
  3804. }
  3805. public class Return : ExpressionStatement
  3806. {
  3807. public Return() : base()
  3808. {
  3809. this.NodeType = NodeType.Return;
  3810. }
  3811. public Return(Expression expression) : base(expression)
  3812. {
  3813. this.NodeType = NodeType.Return;
  3814. }
  3815. public Return(SourceContext sctx)
  3816. : base()
  3817. {
  3818. this.NodeType = NodeType.Return;
  3819. this.SourceContext = sctx;
  3820. }
  3821. public Return(Expression expression, SourceContext sctx)
  3822. : base(expression)
  3823. {
  3824. this.NodeType = NodeType.Return;
  3825. this.SourceContext = sctx;
  3826. }
  3827. }
  3828. public class Yield : ExpressionStatement
  3829. {
  3830. public Yield()
  3831. : base()
  3832. {
  3833. this.NodeType = NodeType.Yield;
  3834. }
  3835. public Yield(Expression expression)
  3836. : base(expression)
  3837. {
  3838. this.NodeType = NodeType.Yield;
  3839. }
  3840. public Yield(Expression expression, SourceContext sctx)
  3841. : base(expression)
  3842. {
  3843. this.NodeType = NodeType.Yield;
  3844. this.SourceContext = sctx;
  3845. }
  3846. }
  3847. public class Try : Statement
  3848. {
  3849. private CatchList catchers;
  3850. private FilterList filters;
  3851. private FaultHandlerList faultHandlers;
  3852. private Finally finallyClause;
  3853. private Block tryBlock;
  3854. public Try()
  3855. : base(NodeType.Try)
  3856. {
  3857. }
  3858. public Try(Block tryBlock, CatchList catchers, FilterList filters, FaultHandlerList faultHandlers, Finally Finally)
  3859. : base(NodeType.Try)
  3860. {
  3861. this.catchers = catchers;
  3862. this.faultHandlers = faultHandlers;
  3863. this.filters = filters;
  3864. this.finallyClause = Finally;
  3865. this.tryBlock = tryBlock;
  3866. }
  3867. public CatchList Catchers
  3868. {
  3869. get { return this.catchers; }
  3870. set { this.catchers = value; }
  3871. }
  3872. public FilterList Filters
  3873. {
  3874. get { return this.filters; }
  3875. set { this.filters = value; }
  3876. }
  3877. public FaultHandlerList FaultHandlers
  3878. {
  3879. get { return this.faultHandlers; }
  3880. set { this.faultHandlers = value; }
  3881. }
  3882. public Finally Finally
  3883. {
  3884. get { return this.finallyClause; }
  3885. set { this.finallyClause = value; }
  3886. }
  3887. public Block TryBlock
  3888. {
  3889. get { return this.tryBlock; }
  3890. set { this.tryBlock = value; }
  3891. }
  3892. }
  3893. public class Catch : Statement
  3894. {
  3895. private Block block;
  3896. private TypeNode type;
  3897. private Expression variable;
  3898. public TypeNode TypeExpression;
  3899. public Catch()
  3900. : base(NodeType.Catch)
  3901. {
  3902. }
  3903. public Catch(Block block, Expression variable, TypeNode type)
  3904. : base(NodeType.Catch)
  3905. {
  3906. this.block = block;
  3907. this.variable = variable;
  3908. this.type = type;
  3909. }
  3910. public Block Block
  3911. {
  3912. get { return this.block; }
  3913. set { this.block = value; }
  3914. }
  3915. public TypeNode Type
  3916. {
  3917. get { return this.type; }
  3918. set { this.type = value; }
  3919. }
  3920. public Expression Variable
  3921. {
  3922. get { return this.variable; }
  3923. set { this.variable = value; }
  3924. }
  3925. }
  3926. public class Finally : Statement
  3927. {
  3928. private Block block;
  3929. public Finally()
  3930. : base(NodeType.Finally)
  3931. {
  3932. }
  3933. public Finally(Block block)
  3934. : base(NodeType.Finally)
  3935. {
  3936. this.block = block;
  3937. }
  3938. public Block Block
  3939. {
  3940. get { return this.block; }
  3941. set { this.block = value; }
  3942. }
  3943. }
  3944. public class EndFinally : Statement
  3945. {
  3946. public EndFinally()
  3947. : base(NodeType.EndFinally)
  3948. {
  3949. }
  3950. }
  3951. public class Filter : Statement
  3952. {
  3953. private Block block;
  3954. private Expression expression;
  3955. public Filter()
  3956. : base(NodeType.Filter)
  3957. {
  3958. }
  3959. public Filter(Block block, Expression expression)
  3960. : base(NodeType.Filter)
  3961. {
  3962. this.block = block;
  3963. this.expression = expression;
  3964. }
  3965. public Block Block
  3966. {
  3967. get { return this.block; }
  3968. set { this.block = value; }
  3969. }
  3970. public Expression Expression
  3971. {
  3972. get { return this.expression; }
  3973. set { this.expression = value; }
  3974. }
  3975. }
  3976. public class EndFilter : Statement
  3977. {
  3978. private Expression value;
  3979. public EndFilter()
  3980. : base(NodeType.EndFilter)
  3981. {
  3982. }
  3983. public EndFilter(Expression value)
  3984. : base(NodeType.EndFilter)
  3985. {
  3986. this.value = value;
  3987. }
  3988. public Expression Value
  3989. {
  3990. get { return this.value; }
  3991. set { this.value = value; }
  3992. }
  3993. }
  3994. public class FaultHandler : Statement
  3995. {
  3996. private Block block;
  3997. public FaultHandler()
  3998. : base(NodeType.FaultHandler)
  3999. {
  4000. }
  4001. public FaultHandler(Block block)
  4002. : base(NodeType.FaultHandler)
  4003. {
  4004. this.block = block;
  4005. }
  4006. public Block Block
  4007. {
  4008. get { return this.block; }
  4009. set { this.block = value; }
  4010. }
  4011. }
  4012. public class Throw : Statement
  4013. {
  4014. private Expression expression;
  4015. public Throw()
  4016. : base(NodeType.Throw)
  4017. {
  4018. }
  4019. public Throw(Expression expression)
  4020. : base(NodeType.Throw)
  4021. {
  4022. this.expression = expression;
  4023. }
  4024. public Throw(Expression expression, SourceContext context)
  4025. : base(NodeType.Throw)
  4026. {
  4027. this.expression = expression;
  4028. this.SourceContext = context;
  4029. }
  4030. public Expression Expression
  4031. {
  4032. get { return this.expression; }
  4033. set { this.expression = value; }
  4034. }
  4035. }
  4036. public class If : Statement
  4037. {
  4038. public Expression Condition;
  4039. public Block TrueBlock;
  4040. public Block FalseBlock;
  4041. public SourceContext ConditionContext;
  4042. public SourceContext ElseContext;
  4043. public SourceContext EndIfContext;
  4044. public If()
  4045. : base(NodeType.If)
  4046. {
  4047. }
  4048. public If(Expression condition, Block trueBlock, Block falseBlock)
  4049. : base(NodeType.If)
  4050. {
  4051. this.Condition = condition;
  4052. if(condition != null)
  4053. this.ConditionContext = condition.SourceContext;
  4054. this.TrueBlock = trueBlock;
  4055. this.FalseBlock = falseBlock;
  4056. }
  4057. }
  4058. public class For : Statement
  4059. {
  4060. public Block Body;
  4061. public Expression Condition;
  4062. public StatementList Incrementer;
  4063. public StatementList Initializer;
  4064. public ExpressionList Invariants;
  4065. public For()
  4066. : base(NodeType.For)
  4067. {
  4068. }
  4069. public For(StatementList initializer, Expression condition, StatementList incrementer, Block body)
  4070. : base(NodeType.For)
  4071. {
  4072. this.Body = body;
  4073. this.Condition = condition;
  4074. this.Incrementer = incrementer;
  4075. this.Initializer = initializer;
  4076. }
  4077. }
  4078. public class ForEach : Statement
  4079. {
  4080. public Block Body;
  4081. public Expression SourceEnumerable;
  4082. public BlockScope ScopeForTemporaryVariables;
  4083. public Expression TargetVariable;
  4084. public TypeNode TargetVariableType;
  4085. public TypeNode TargetVariableTypeExpression;
  4086. public Expression InductionVariable;
  4087. public ExpressionList Invariants;
  4088. public bool StatementTerminatesNormallyIfEnumerableIsNull = true;
  4089. public bool StatementTerminatesNormallyIfEnumeratorIsNull = true;
  4090. public ForEach()
  4091. : base(NodeType.ForEach)
  4092. {
  4093. }
  4094. public ForEach(TypeNode targetVariableType, Expression targetVariable, Expression sourceEnumerable, Block body)
  4095. : base(NodeType.ForEach)
  4096. {
  4097. this.TargetVariable = targetVariable;
  4098. this.TargetVariableType = targetVariableType;
  4099. this.SourceEnumerable = sourceEnumerable;
  4100. this.Body = body;
  4101. }
  4102. }
  4103. public class Exit : Statement
  4104. {
  4105. public Literal Level;
  4106. public Exit()
  4107. : base(NodeType.Exit)
  4108. {
  4109. }
  4110. public Exit(Literal level)
  4111. : base(NodeType.Exit)
  4112. {
  4113. this.Level = level;
  4114. }
  4115. }
  4116. public class Continue : Statement
  4117. {
  4118. public Literal Level;
  4119. public Continue()
  4120. : base(NodeType.Continue)
  4121. {
  4122. }
  4123. public Continue(Literal level)
  4124. : base(NodeType.Continue)
  4125. {
  4126. this.Level = level;
  4127. }
  4128. }
  4129. public class Switch : Statement
  4130. {
  4131. public SwitchCaseList Cases;
  4132. public Expression Expression;
  4133. public Local Nullable;
  4134. public Expression NullableExpression;
  4135. public BlockScope Scope;
  4136. public Switch()
  4137. : base(NodeType.Switch)
  4138. {
  4139. }
  4140. public Switch(Expression expression, SwitchCaseList cases)
  4141. : base(NodeType.Switch)
  4142. {
  4143. this.Cases = cases;
  4144. this.Expression = expression;
  4145. }
  4146. }
  4147. public class SwitchCase : Node
  4148. {
  4149. public Block Body;
  4150. public Expression Label;
  4151. public SwitchCase()
  4152. : base(NodeType.SwitchCase)
  4153. {
  4154. }
  4155. public SwitchCase(Expression label, Block body)
  4156. : base(NodeType.SwitchCase)
  4157. {
  4158. this.Body = body;
  4159. this.Label = label;
  4160. }
  4161. }
  4162. public class GotoCase : Statement
  4163. {
  4164. public Expression CaseLabel;
  4165. public GotoCase(Expression caseLabel)
  4166. : base(NodeType.GotoCase)
  4167. {
  4168. this.CaseLabel = caseLabel;
  4169. }
  4170. }
  4171. public class SwitchInstruction : Statement
  4172. {
  4173. private Expression expression;
  4174. private BlockList targets;
  4175. public SwitchInstruction()
  4176. : base(NodeType.SwitchInstruction)
  4177. {
  4178. }
  4179. public SwitchInstruction(Expression expression, BlockList targets)
  4180. : base(NodeType.SwitchInstruction)
  4181. {
  4182. this.expression = expression;
  4183. this.targets = targets;
  4184. }
  4185. public Expression Expression
  4186. {
  4187. get { return this.expression; }
  4188. set { this.expression = value; }
  4189. }
  4190. public BlockList Targets
  4191. {
  4192. get { return this.targets; }
  4193. set { this.targets = value; }
  4194. }
  4195. }
  4196. public class Typeswitch : Statement
  4197. {
  4198. public TypeswitchCaseList Cases;
  4199. public Expression Expression;
  4200. public Typeswitch()
  4201. : base(NodeType.Typeswitch)
  4202. {
  4203. }
  4204. public Typeswitch(Expression expression, TypeswitchCaseList cases)
  4205. : base(NodeType.Typeswitch)
  4206. {
  4207. this.Cases = cases;
  4208. this.Expression = expression;
  4209. }
  4210. }
  4211. public class TypeswitchCase : Node
  4212. {
  4213. public Block Body;
  4214. public TypeNode LabelType;
  4215. public TypeNode LabelTypeExpression;
  4216. public Expression LabelVariable;
  4217. public TypeswitchCase()
  4218. : base(NodeType.TypeswitchCase)
  4219. {
  4220. }
  4221. public TypeswitchCase(TypeNode labelType, Expression labelVariable, Block body)
  4222. : base(NodeType.TypeswitchCase)
  4223. {
  4224. this.Body = body;
  4225. this.LabelType = labelType;
  4226. this.LabelVariable = labelVariable;
  4227. }
  4228. }
  4229. public class While : Statement
  4230. {
  4231. public Expression Condition;
  4232. public ExpressionList Invariants;
  4233. public Block Body;
  4234. public While()
  4235. : base(NodeType.While)
  4236. {
  4237. }
  4238. public While(Expression condition, Block body)
  4239. : base(NodeType.While)
  4240. {
  4241. this.Condition = condition;
  4242. this.Body = body;
  4243. }
  4244. }
  4245. public class DoWhile : Statement
  4246. {
  4247. public Expression Condition;
  4248. public ExpressionList Invariants;
  4249. public Block Body;
  4250. public DoWhile()
  4251. : base(NodeType.DoWhile)
  4252. {
  4253. }
  4254. public DoWhile(Expression condition, Block body)
  4255. : base(NodeType.DoWhile)
  4256. {
  4257. this.Condition = condition;
  4258. this.Body = body;
  4259. }
  4260. }
  4261. public class Repeat : Statement
  4262. {
  4263. public Expression Condition;
  4264. public Block Body;
  4265. public Repeat()
  4266. : base(NodeType.Repeat)
  4267. {
  4268. }
  4269. public Repeat(Expression condition, Block body)
  4270. : base(NodeType.Repeat)
  4271. {
  4272. this.Condition = condition;
  4273. this.Body = body;
  4274. }
  4275. }
  4276. public class Fixed : Statement
  4277. {
  4278. public Statement Declarators;
  4279. public Block Body;
  4280. public BlockScope ScopeForTemporaryVariables;
  4281. public Fixed()
  4282. : base(NodeType.Fixed)
  4283. {
  4284. }
  4285. }
  4286. public class Lock : Statement
  4287. {
  4288. public Expression Guard;
  4289. public Block Body;
  4290. public BlockScope ScopeForTemporaryVariable;
  4291. public Lock()
  4292. : base(NodeType.Lock)
  4293. {
  4294. }
  4295. }
  4296. public class ResourceUse : Statement
  4297. {
  4298. public Statement ResourceAcquisition;
  4299. public Block Body;
  4300. public BlockScope ScopeForTemporaryVariable;
  4301. public ResourceUse()
  4302. : base(NodeType.ResourceUse)
  4303. {
  4304. }
  4305. }
  4306. public class Goto : Statement
  4307. {
  4308. public Identifier TargetLabel;
  4309. public Goto()
  4310. : base(NodeType.Goto)
  4311. {
  4312. }
  4313. public Goto(Identifier targetLabel)
  4314. : base(NodeType.Goto)
  4315. {
  4316. this.TargetLabel = targetLabel;
  4317. }
  4318. }
  4319. public class VariableDeclaration : Statement
  4320. {
  4321. public Expression Initializer;
  4322. public Identifier Name;
  4323. public TypeNode Type;
  4324. public TypeNode TypeExpression;
  4325. public Field Field;
  4326. public VariableDeclaration()
  4327. : base(NodeType.VariableDeclaration)
  4328. {
  4329. }
  4330. public VariableDeclaration(Identifier name, TypeNode type, Expression initializer)
  4331. : base(NodeType.VariableDeclaration)
  4332. {
  4333. this.Initializer = initializer;
  4334. this.Name = name;
  4335. this.Type = type;
  4336. }
  4337. }
  4338. public class LocalDeclaration : Node
  4339. {
  4340. public Field Field;
  4341. public Identifier Name;
  4342. public Expression InitialValue;
  4343. /// <summary>
  4344. /// Used when converting a declaration with initializer into an assignment statement.
  4345. /// Usually Nop, but could be set to CopyReference to avoid dereferencing on either side.
  4346. /// </summary>
  4347. public NodeType AssignmentNodeType = NodeType.Nop;
  4348. public LocalDeclaration()
  4349. : base(NodeType.LocalDeclaration)
  4350. {
  4351. }
  4352. public LocalDeclaration(Identifier name, Expression initialValue)
  4353. : base(NodeType.LocalDeclaration)
  4354. {
  4355. this.Name = name;
  4356. this.InitialValue = initialValue;
  4357. }
  4358. public LocalDeclaration(Identifier name, Expression initialValue, NodeType assignmentNodeType)
  4359. : base(NodeType.LocalDeclaration)
  4360. {
  4361. this.Name = name;
  4362. this.InitialValue = initialValue;
  4363. this.AssignmentNodeType = assignmentNodeType;
  4364. }
  4365. }
  4366. public class LocalDeclarationsStatement : Statement
  4367. {
  4368. public bool Constant;
  4369. public bool InitOnly;
  4370. public TypeNode Type;
  4371. public TypeNode TypeExpression;
  4372. public LocalDeclarationList Declarations;
  4373. public LocalDeclarationsStatement()
  4374. : base(NodeType.LocalDeclarationsStatement)
  4375. {
  4376. }
  4377. public LocalDeclarationsStatement(LocalDeclaration ldecl, TypeNode type)
  4378. : base(NodeType.LocalDeclarationsStatement)
  4379. {
  4380. Declarations = new LocalDeclarationList();
  4381. Declarations.Add(ldecl);
  4382. this.Type = type;
  4383. }
  4384. }
  4385. public class StatementSnippet : Statement
  4386. {
  4387. public IParserFactory ParserFactory;
  4388. public StatementSnippet()
  4389. : base(NodeType.StatementSnippet)
  4390. {
  4391. }
  4392. public StatementSnippet(IParserFactory parserFactory, SourceContext sctx)
  4393. : base(NodeType.StatementSnippet)
  4394. {
  4395. this.ParserFactory = parserFactory;
  4396. this.SourceContext = sctx;
  4397. }
  4398. }
  4399. /// <summary>
  4400. /// Associates an identifier with a type or a namespace or a Uri or a list of assemblies.
  4401. /// In C# alias identifiers are used as root identifiers in qualified expressions, or as identifier prefixes.
  4402. /// </summary>
  4403. public class AliasDefinition : Node
  4404. {
  4405. /// <summary>The identifier that serves as an alias for the type, namespace, Uri or list of assemblies.</summary>
  4406. public Identifier Alias;
  4407. /// <summary>The list of assemblies being aliased.</summary>
  4408. public AssemblyReferenceList AliasedAssemblies;
  4409. /// <summary>The expression that was (or should be) resolved into a type, namespace or Uri.</summary>
  4410. public Expression AliasedExpression;
  4411. /// <summary>The namespace being aliased.</summary>
  4412. public Identifier AliasedNamespace;
  4413. /// <summary>A reference to the type being aliased.</summary>
  4414. public TypeReference AliasedType;
  4415. /// <summary>The Uri being aliased.</summary>
  4416. public Identifier AliasedUri;
  4417. /// <summary>
  4418. /// If an alias definition conflicts with a type definition and this causes an ambiguity, the conflicting type is stored here
  4419. /// by the code that detects the ambiguity. A later visitor is expected to report an error if this is not null.
  4420. /// </summary>
  4421. public TypeNode ConflictingType;
  4422. public bool RestrictToInterfaces;
  4423. public bool RestrictToClassesAndInterfaces;
  4424. public AliasDefinition()
  4425. : base(NodeType.AliasDefinition)
  4426. {
  4427. }
  4428. public AliasDefinition(Identifier alias, Expression aliasedExpression)
  4429. : base(NodeType.AliasDefinition)
  4430. {
  4431. this.Alias = alias;
  4432. this.AliasedExpression = aliasedExpression;
  4433. }
  4434. public AliasDefinition(Identifier alias, Expression aliasedExpression, SourceContext sctx)
  4435. : base(NodeType.AliasDefinition)
  4436. {
  4437. this.Alias = alias;
  4438. this.AliasedExpression = aliasedExpression;
  4439. this.SourceContext = sctx;
  4440. }
  4441. }
  4442. public class UsedNamespace : Node
  4443. {
  4444. public Identifier Namespace;
  4445. public Identifier URI;
  4446. public UsedNamespace()
  4447. : base(NodeType.UsedNamespace)
  4448. {
  4449. }
  4450. public UsedNamespace(Identifier Namespace)
  4451. : base(NodeType.UsedNamespace)
  4452. {
  4453. this.Namespace = Namespace;
  4454. }
  4455. public UsedNamespace(Identifier Namespace, SourceContext sctx)
  4456. : base(NodeType.UsedNamespace)
  4457. {
  4458. this.Namespace = Namespace;
  4459. this.SourceContext = sctx;
  4460. }
  4461. }
  4462. public class ExceptionHandler : Node
  4463. {
  4464. private NodeType handlerType;
  4465. private Block tryStartBlock;
  4466. private Block blockAfterTryEnd;
  4467. private Block handlerStartBlock;
  4468. private Block blockAfterHandlerEnd;
  4469. private Block filterExpression;
  4470. private TypeNode filterType;
  4471. public ExceptionHandler()
  4472. : base(NodeType.ExceptionHandler)
  4473. {
  4474. }
  4475. public NodeType HandlerType
  4476. {
  4477. get { return this.handlerType; }
  4478. set { this.handlerType = value; }
  4479. }
  4480. public Block TryStartBlock
  4481. {
  4482. get { return this.tryStartBlock; }
  4483. set { this.tryStartBlock = value; }
  4484. }
  4485. public Block BlockAfterTryEnd
  4486. {
  4487. get { return this.blockAfterTryEnd; }
  4488. set { this.blockAfterTryEnd = value; }
  4489. }
  4490. public Block HandlerStartBlock
  4491. {
  4492. get { return this.handlerStartBlock; }
  4493. set { this.handlerStartBlock = value; }
  4494. }
  4495. public Block BlockAfterHandlerEnd
  4496. {
  4497. get { return this.blockAfterHandlerEnd; }
  4498. set { this.blockAfterHandlerEnd = value; }
  4499. }
  4500. public Block FilterExpression
  4501. {
  4502. get { return this.filterExpression; }
  4503. set { this.filterExpression = value; }
  4504. }
  4505. public TypeNode FilterType
  4506. {
  4507. get { return this.filterType; }
  4508. set { this.filterType = value; }
  4509. }
  4510. }
  4511. public class AttributeNode : Node
  4512. {
  4513. public bool IsPseudoAttribute;
  4514. public AttributeNode()
  4515. : base(NodeType.Attribute)
  4516. {
  4517. }
  4518. public AttributeNode(Expression constructor, ExpressionList expressions)
  4519. : base(NodeType.Attribute)
  4520. {
  4521. this.constructor = constructor;
  4522. this.expressions = expressions;
  4523. this.target = AttributeTargets.All;
  4524. }
  4525. public AttributeNode(Expression constructor, ExpressionList expressions, AttributeTargets target)
  4526. : base(NodeType.Attribute)
  4527. {
  4528. this.constructor = constructor;
  4529. this.expressions = expressions;
  4530. this.target = target;
  4531. }
  4532. private Expression constructor;
  4533. public Expression Constructor
  4534. {
  4535. get { return this.constructor; }
  4536. set { this.constructor = value; }
  4537. }
  4538. private ExpressionList expressions;
  4539. /// <summary>
  4540. /// Invariant: positional arguments occur first and in order in the expression list. Named arguments
  4541. /// follow positional arguments in any order.
  4542. /// </summary>
  4543. public ExpressionList Expressions
  4544. {
  4545. get { return this.expressions; }
  4546. set { this.expressions = value; }
  4547. }
  4548. private AttributeTargets target;
  4549. public AttributeTargets Target
  4550. {
  4551. get { return this.target; }
  4552. set { this.target = value; }
  4553. }
  4554. private bool allowMultiple;
  4555. public virtual bool AllowMultiple
  4556. {
  4557. get
  4558. {
  4559. if(this.usageAttribute == null)
  4560. this.GetUsageInformation();
  4561. return this.allowMultiple;
  4562. }
  4563. set
  4564. {
  4565. this.allowMultiple = value;
  4566. }
  4567. }
  4568. private bool inherited;
  4569. public virtual bool Inherited
  4570. {
  4571. get
  4572. {
  4573. if(this.usageAttribute == null)
  4574. this.GetUsageInformation();
  4575. return this.inherited;
  4576. }
  4577. set
  4578. {
  4579. this.inherited = value;
  4580. }
  4581. }
  4582. private AttributeTargets validOn;
  4583. public virtual AttributeTargets ValidOn
  4584. {
  4585. get
  4586. {
  4587. if(this.usageAttribute == null)
  4588. this.GetUsageInformation();
  4589. return this.validOn;
  4590. }
  4591. set
  4592. {
  4593. this.validOn = value;
  4594. }
  4595. }
  4596. private TypeNode type;
  4597. public virtual TypeNode Type
  4598. {
  4599. get
  4600. {
  4601. if(this.type == null)
  4602. {
  4603. MemberBinding mb = this.Constructor as MemberBinding;
  4604. Member cons = mb == null ? null : mb.BoundMember;
  4605. this.type = cons == null ? null : cons.DeclaringType;
  4606. }
  4607. return this.type;
  4608. }
  4609. set
  4610. {
  4611. this.type = value;
  4612. }
  4613. }
  4614. private AttributeNode usageAttribute;
  4615. private void GetUsageInformation()
  4616. {
  4617. AttributeNode attr = null;
  4618. TypeNode attrType = this.Type;
  4619. while(attrType != null)
  4620. {
  4621. attr = attrType.GetAttribute(SystemTypes.AttributeUsageAttribute);
  4622. if(attr != null)
  4623. break;
  4624. attrType = attrType.BaseType;
  4625. }
  4626. if(attr == null)
  4627. {
  4628. this.usageAttribute = AttributeNode.DoesNotExist;
  4629. return;
  4630. }
  4631. ExpressionList args = attr.Expressions;
  4632. if(args == null || args.Count < 1)
  4633. return;
  4634. Literal lit = args[0] as Literal;
  4635. if(lit == null || !(lit.Value is int))
  4636. return;
  4637. //^ assert lit.Value != null;
  4638. this.validOn = (AttributeTargets)(int)lit.Value;
  4639. for(int i = 1, n = args.Count; i < n; i++)
  4640. {
  4641. NamedArgument narg = args[i] as NamedArgument;
  4642. if(narg == null || narg.Name == null)
  4643. continue;
  4644. lit = narg.Value as Literal;
  4645. if(lit == null)
  4646. continue;
  4647. if(narg.Name.UniqueIdKey == StandardIds.AllowMultiple.UniqueIdKey)
  4648. {
  4649. if(lit.Value == null || !(lit.Value is bool))
  4650. continue;
  4651. this.allowMultiple = (bool)lit.Value;
  4652. }
  4653. else if(narg.Name.UniqueIdKey == StandardIds.Inherited.UniqueIdKey)
  4654. {
  4655. if(lit.Value == null || !(lit.Value is bool))
  4656. continue;
  4657. this.inherited = (bool)lit.Value;
  4658. }
  4659. }
  4660. }
  4661. public static readonly AttributeNode DoesNotExist = new AttributeNode();
  4662. public virtual System.Attribute GetRuntimeAttribute()
  4663. {
  4664. MemberBinding mb = this.Constructor as MemberBinding;
  4665. if(mb == null)
  4666. return null;
  4667. InstanceInitializer constr = mb.BoundMember as InstanceInitializer;
  4668. if(constr == null)
  4669. return null;
  4670. ParameterList parameters = constr.Parameters;
  4671. int paramCount = parameters == null ? 0 : parameters.Count;
  4672. object[] argumentValues = new object[paramCount];
  4673. ExpressionList argumentExpressions = this.Expressions;
  4674. int exprCount = argumentExpressions == null ? 0 : argumentExpressions.Count;
  4675. for(int i = 0, j = 0; i < paramCount; i++)
  4676. {
  4677. if(j >= exprCount)
  4678. return null;
  4679. //^ assert argumentExpressions != null;
  4680. Expression argExpr = argumentExpressions[j++];
  4681. Literal lit = argExpr as Literal;
  4682. if(lit == null)
  4683. continue;
  4684. argumentValues[i] = this.GetCoercedLiteralValue(lit.Type, lit.Value);
  4685. }
  4686. System.Attribute attr = this.ConstructAttribute(constr, argumentValues);
  4687. if(attr == null)
  4688. return null;
  4689. for(int i = 0; i < exprCount; i++)
  4690. {
  4691. //^ assert argumentExpressions != null;
  4692. NamedArgument namedArg = argumentExpressions[i] as NamedArgument;
  4693. if(namedArg == null)
  4694. continue;
  4695. if(namedArg.Name == null)
  4696. continue;
  4697. Literal lit = namedArg.Value as Literal;
  4698. if(lit == null)
  4699. continue;
  4700. object val = this.GetCoercedLiteralValue(lit.Type, lit.Value);
  4701. if(namedArg.IsCustomAttributeProperty)
  4702. {
  4703. TypeNode t = constr.DeclaringType;
  4704. while(t != null)
  4705. {
  4706. Property prop = t.GetProperty(namedArg.Name);
  4707. if(prop != null)
  4708. {
  4709. this.SetAttributeProperty(prop, attr, val);
  4710. t = null;
  4711. }
  4712. else
  4713. t = t.BaseType;
  4714. }
  4715. }
  4716. else
  4717. {
  4718. TypeNode t = constr.DeclaringType;
  4719. while(t != null)
  4720. {
  4721. Field f = constr.DeclaringType.GetField(namedArg.Name);
  4722. if(f != null)
  4723. {
  4724. System.Reflection.FieldInfo fieldInfo = f.GetFieldInfo();
  4725. if(fieldInfo != null)
  4726. fieldInfo.SetValue(attr, val);
  4727. t = null;
  4728. }
  4729. else
  4730. t = t.BaseType;
  4731. }
  4732. }
  4733. }
  4734. return attr;
  4735. }
  4736. /// <summary>
  4737. /// Gets the value of the literal coercing literals of TypeNode, EnumNode, TypeNode[], and EnumNode[] as needed.
  4738. /// </summary>
  4739. /// <param name="type">A TypeNode representing the type of the literal</param>
  4740. /// <param name="value">The value of the literal</param>
  4741. /// <returns>An object that has been coerced to the appropriate runtime type</returns>
  4742. protected object GetCoercedLiteralValue(TypeNode type, object value)
  4743. {
  4744. if(type == null || value == null)
  4745. return null;
  4746. switch(type.typeCode)
  4747. {
  4748. case ElementType.Class:
  4749. return ((TypeNode)value).GetRuntimeType();
  4750. case ElementType.ValueType:
  4751. return System.Enum.ToObject(type.GetRuntimeType(), value);
  4752. case ElementType.SzArray:
  4753. return this.GetCoercedArrayLiteral((ArrayType)type, (Array)value);
  4754. default:
  4755. Literal lit = value as Literal;
  4756. if(lit != null && type == CoreSystemTypes.Object && lit.Type is EnumNode)
  4757. return this.GetCoercedLiteralValue(lit.Type, lit.Value);
  4758. break;
  4759. }
  4760. return value;
  4761. }
  4762. /// <summary>
  4763. /// Gets the array literal in arrayValue coercing TypeNode[] and EnumNode[] as needed.
  4764. /// </summary>
  4765. /// <param name="arrayType">A TypeNode representing the array type</param>
  4766. /// <param name="arrayValue">The value of the array literal to coerce</param>
  4767. /// <returns>An Array object that has been coerced to the appropriate runtime type</returns>
  4768. protected Array GetCoercedArrayLiteral(ArrayType arrayType, Array arrayValue)
  4769. {
  4770. if(arrayType == null)
  4771. return null;
  4772. if(arrayValue == null)
  4773. return null;
  4774. // Multi-dimensional arrays are not legal in attribute instances according section 17.1.3 of the C# 1.0 spec
  4775. if(arrayValue.Rank != 1)
  4776. return null;
  4777. TypeNode elemType = arrayType.ElementType;
  4778. if(elemType.typeCode != ElementType.ValueType && elemType.typeCode != ElementType.Class)
  4779. return arrayValue;
  4780. int arraySize = arrayValue.GetLength(0);
  4781. Type et = elemType.GetRuntimeType();
  4782. if(et == null)
  4783. return null;
  4784. Array val = Array.CreateInstance(et, arraySize);
  4785. for(int i = 0; i < arraySize; i++)
  4786. val.SetValue(this.GetCoercedLiteralValue(elemType, arrayValue.GetValue(i)), i);
  4787. return val;
  4788. }
  4789. private void SetAttributeProperty(Property/*!*/ prop, System.Attribute attr, object val)
  4790. {
  4791. //This could execute partially trusted code, so set up a very restrictive execution environment
  4792. //TODO: skip this if the attribute is from a trusted assembly
  4793. System.Reflection.PropertyInfo propInfo = prop.GetPropertyInfo();
  4794. if(propInfo == null)
  4795. return;
  4796. //Because we invoke the setter through reflection, a stack walk is performed. The following two commented-out statements
  4797. //would cause the stack walk to fail.
  4798. //For now, we will run the setter in full trust until we work around this.
  4799. //For VS2005 and later, we will construct a DynamicMethod, wrap it in a delegate, and invoke that.
  4800. //System.Security.PermissionSet perm = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None);
  4801. //perm.PermitOnly();
  4802. try
  4803. {
  4804. propInfo.SetValue(attr, val, null);
  4805. }
  4806. catch { }
  4807. }
  4808. private System.Attribute ConstructAttribute(InstanceInitializer/*!*/ constr, object[] argumentValues)
  4809. {
  4810. //This could execute partially trusted code, so set up a very restrictive execution environment
  4811. //TODO: skip this if the attribute is from a trusted assembly
  4812. System.Reflection.ConstructorInfo consInfo = constr.GetConstructorInfo();
  4813. if(consInfo == null)
  4814. return null;
  4815. //Because we invoke the constructor through reflection, a stack walk is performed. The following two commented-out statements
  4816. //would cause the stack walk to fail.
  4817. //For VS2003 and earlier, we will run the constructor in full trust.
  4818. //For VS2005 and later, we will construct a DynamicMethod, wrap it in a delegate, and invoke that.
  4819. //System.Security.PermissionSet perm = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None);
  4820. //perm.PermitOnly();
  4821. try
  4822. {
  4823. return consInfo.Invoke(argumentValues) as System.Attribute;
  4824. }
  4825. catch { }
  4826. return null;
  4827. }
  4828. public Expression GetPositionalArgument(int position)
  4829. {
  4830. if(this.Expressions == null || this.Expressions.Count <= position)
  4831. return null;
  4832. Expression e = this.Expressions[position];
  4833. NamedArgument na = e as NamedArgument;
  4834. if(na != null)
  4835. return null;
  4836. return e;
  4837. }
  4838. public Expression GetNamedArgument(Identifier name)
  4839. {
  4840. if(name == null || this.Expressions == null)
  4841. return null;
  4842. foreach(Expression e in this.Expressions)
  4843. {
  4844. NamedArgument na = e as NamedArgument;
  4845. if(na == null)
  4846. continue;
  4847. if(na.Name == null)
  4848. continue;
  4849. if(na.Name.UniqueIdKey == name.UniqueIdKey)
  4850. return na.Value;
  4851. }
  4852. return null;
  4853. }
  4854. }
  4855. public class SecurityAttribute : Node
  4856. {
  4857. public SecurityAttribute()
  4858. : base(NodeType.SecurityAttribute)
  4859. {
  4860. }
  4861. private System.Security.Permissions.SecurityAction action;
  4862. public System.Security.Permissions.SecurityAction Action
  4863. {
  4864. get { return this.action; }
  4865. set { this.action = value; }
  4866. }
  4867. private AttributeList permissionAttributes;
  4868. public AttributeList PermissionAttributes
  4869. {
  4870. get { return this.permissionAttributes; }
  4871. set { this.permissionAttributes = value; }
  4872. }
  4873. protected string serializedPermissions;
  4874. public string SerializedPermissions
  4875. {
  4876. get
  4877. {
  4878. if(this.serializedPermissions == null && this.PermissionAttributes != null)
  4879. {
  4880. lock(this)
  4881. {
  4882. if(this.serializedPermissions != null)
  4883. return this.serializedPermissions;
  4884. System.Security.PermissionSet permissions = this.Permissions;
  4885. if(permissions == null)
  4886. return null;
  4887. System.Security.SecurityElement xml = permissions.ToXml();
  4888. if(xml == null)
  4889. return null;
  4890. this.serializedPermissions = xml.ToString();
  4891. //TODO: if the target platform is different from the host platform, replace references to host platform
  4892. //assemblies with references to target platform assemblies
  4893. }
  4894. }
  4895. return this.serializedPermissions;
  4896. }
  4897. set
  4898. {
  4899. this.serializedPermissions = value;
  4900. }
  4901. }
  4902. protected System.Security.PermissionSet permissions;
  4903. public System.Security.PermissionSet Permissions
  4904. {
  4905. get
  4906. {
  4907. if(this.permissions == null)
  4908. {
  4909. lock(this)
  4910. {
  4911. if(this.permissions != null)
  4912. return this.permissions;
  4913. System.Security.PermissionSet permissions = null;
  4914. if(this.PermissionAttributes != null)
  4915. {
  4916. permissions = this.InstantiatePermissionAttributes();
  4917. }
  4918. else if(this.serializedPermissions != null)
  4919. {
  4920. permissions = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None);
  4921. permissions.FromXml(this.GetSecurityElement());
  4922. }
  4923. this.permissions = permissions;
  4924. }
  4925. }
  4926. return this.permissions;
  4927. }
  4928. set
  4929. {
  4930. this.permissions = value;
  4931. }
  4932. }
  4933. protected System.Security.SecurityElement GetSecurityElement()
  4934. {
  4935. return System.Security.SecurityElement.FromString(this.serializedPermissions);
  4936. }
  4937. protected System.Security.PermissionSet InstantiatePermissionAttributes()
  4938. {
  4939. System.Security.PermissionSet permissions = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None);
  4940. AttributeList permissionAttributes = this.PermissionAttributes;
  4941. for(int i = 0, n = permissionAttributes == null ? 0 : permissionAttributes.Count; i < n; i++)
  4942. {
  4943. //^ assert permissionAttributes != null;
  4944. object result = this.GetPermissionOrSetOfPermissionsFromAttribute(permissionAttributes[i]);
  4945. if(result == null)
  4946. continue;
  4947. if(result is System.Security.PermissionSet)
  4948. permissions = permissions.Union((System.Security.PermissionSet)result);
  4949. else
  4950. {
  4951. System.Security.IPermission permission = result as System.Security.IPermission;
  4952. if(permission == null)
  4953. continue;
  4954. permissions.AddPermission(permission);
  4955. }
  4956. }
  4957. return permissions;
  4958. }
  4959. protected object GetPermissionOrSetOfPermissionsFromAttribute(AttributeNode attr)
  4960. {
  4961. if(attr == null)
  4962. return null;
  4963. System.Security.Permissions.SecurityAttribute secAttr = attr.GetRuntimeAttribute() as System.Security.Permissions.SecurityAttribute;
  4964. if(secAttr == null)
  4965. return null;
  4966. System.Security.Permissions.PermissionSetAttribute pSetAttr = secAttr as System.Security.Permissions.PermissionSetAttribute;
  4967. if(pSetAttr != null)
  4968. return pSetAttr.CreatePermissionSet();
  4969. else
  4970. return this.CreatePermission(secAttr);
  4971. }
  4972. private System.Security.IPermission CreatePermission(System.Security.Permissions.SecurityAttribute/*!*/ secAttr)
  4973. {
  4974. //This could execute partially trusted code, so set up a very restrictive execution environment
  4975. System.Security.PermissionSet perm = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None);
  4976. //TODO: add permissions if the attribute is from a trusted assembly
  4977. perm.PermitOnly();
  4978. try
  4979. {
  4980. return secAttr.CreatePermission();
  4981. }
  4982. catch { }
  4983. return null;
  4984. }
  4985. }
  4986. public struct Resource
  4987. {
  4988. private bool isPublic;
  4989. private string name;
  4990. private Module definingModule;
  4991. private byte[] data;
  4992. public bool IsPublic
  4993. {
  4994. get { return this.isPublic; }
  4995. set { this.isPublic = value; }
  4996. }
  4997. public string Name
  4998. {
  4999. get { return this.name; }
  5000. set { this.name = value; }
  5001. }
  5002. public Module DefiningModule
  5003. {
  5004. get { return this.definingModule; }
  5005. set { this.definingModule = value; }
  5006. }
  5007. public byte[] Data
  5008. {
  5009. get { return this.data; }
  5010. set { this.data = value; }
  5011. }
  5012. }
  5013. public struct Win32Resource
  5014. {
  5015. private string typeName;
  5016. private int typeId;
  5017. private string name;
  5018. private int id;
  5019. private int languageId;
  5020. private int codePage;
  5021. private byte[] data;
  5022. public string TypeName
  5023. {
  5024. get { return this.typeName; }
  5025. set { this.typeName = value; }
  5026. }
  5027. public int TypeId
  5028. {
  5029. get { return this.typeId; }
  5030. set { this.typeId = value; }
  5031. }
  5032. public string Name
  5033. {
  5034. get { return this.name; }
  5035. set { this.name = value; }
  5036. }
  5037. public int Id
  5038. {
  5039. get { return this.id; }
  5040. set { this.id = value; }
  5041. }
  5042. public int LanguageId
  5043. {
  5044. get { return this.languageId; }
  5045. set { this.languageId = value; }
  5046. }
  5047. public int CodePage
  5048. {
  5049. get { return this.codePage; }
  5050. set { this.codePage = value; }
  5051. }
  5052. public byte[] Data
  5053. {
  5054. get { return this.data; }
  5055. set { this.data = value; }
  5056. }
  5057. }
  5058. public class Module : Node, IDisposable
  5059. {
  5060. internal Reader reader;
  5061. public delegate void TypeNodeListProvider(Module/*!*/ module);
  5062. protected TypeNodeListProvider provideTypeNodeList;
  5063. public delegate TypeNode TypeNodeProvider(Identifier/*!*/ @namespace, Identifier/*!*/ name);
  5064. protected TypeNodeProvider provideTypeNode;
  5065. protected TrivialHashtable namespaceTable = new TrivialHashtable();
  5066. protected NamespaceList namespaceList;
  5067. protected int savedTypesLength;
  5068. public delegate void CustomAttributeProvider(Module/*!*/ module);
  5069. protected CustomAttributeProvider provideCustomAttributes;
  5070. public delegate void ResourceProvider(Module/*!*/ module);
  5071. protected ResourceProvider provideResources;
  5072. public delegate AssemblyNode AssemblyReferenceResolver(AssemblyReference/*!*/ assemblyReference, Module/*!*/ referencingModule);
  5073. public event AssemblyReferenceResolver AssemblyReferenceResolution;
  5074. public event AssemblyReferenceResolver AssemblyReferenceResolutionAfterProbingFailed;
  5075. public delegate void PostAssemblyLoadProcessor(AssemblyNode loadedAssembly);
  5076. public event PostAssemblyLoadProcessor AfterAssemblyLoad;
  5077. public delegate XmlDocument DocumentationResolver(Module referencingModule);
  5078. public event DocumentationResolver DocumentationResolution = null;
  5079. public bool IsNormalized;
  5080. internal int FileAlignment = 512;
  5081. internal readonly static object GlobalLock = new object();
  5082. public Module() : base(NodeType.Module)
  5083. {
  5084. this.IsNormalized = false;
  5085. }
  5086. public Module(TypeNodeProvider provider, TypeNodeListProvider listProvider, CustomAttributeProvider provideCustomAttributes, ResourceProvider provideResources)
  5087. : base(NodeType.Module)
  5088. {
  5089. this.provideCustomAttributes = provideCustomAttributes;
  5090. this.provideResources = provideResources;
  5091. this.provideTypeNode = provider;
  5092. this.provideTypeNodeList = listProvider;
  5093. this.IsNormalized = true;
  5094. }
  5095. public virtual void Dispose()
  5096. {
  5097. if(this.reader != null)
  5098. this.reader.Dispose();
  5099. this.reader = null;
  5100. ModuleReferenceList mrefs = this.moduleReferences;
  5101. for(int i = 0, n = mrefs == null ? 0 : mrefs.Count; i < n; i++)
  5102. {
  5103. //^ assert mrefs != null;
  5104. ModuleReference mr = mrefs[i];
  5105. if(mr != null && mr.Module == null)
  5106. continue;
  5107. mr.Module.Dispose();
  5108. }
  5109. this.moduleReferences = null;
  5110. GC.SuppressFinalize(this);
  5111. }
  5112. private AssemblyReferenceList assemblyReferences;
  5113. public AssemblyReferenceList AssemblyReferences
  5114. {
  5115. get { return this.assemblyReferences; }
  5116. set { this.assemblyReferences = value; }
  5117. }
  5118. private AssemblyNode containingAssembly;
  5119. /// <summary>The assembly, if any, that includes this module in its ModuleReferences.</summary>
  5120. public AssemblyNode ContainingAssembly
  5121. {
  5122. get { return this.containingAssembly; }
  5123. set { this.containingAssembly = value; }
  5124. }
  5125. private string directory;
  5126. public string Directory
  5127. {
  5128. get { return this.directory; }
  5129. set { this.directory = value; }
  5130. }
  5131. private AssemblyHashAlgorithm hashAlgorithm = AssemblyHashAlgorithm.SHA1;
  5132. public AssemblyHashAlgorithm HashAlgorithm
  5133. {
  5134. get { return this.hashAlgorithm; }
  5135. set { this.hashAlgorithm = value; }
  5136. }
  5137. private byte[] hashValue;
  5138. public byte[] HashValue
  5139. {
  5140. get { return this.hashValue; }
  5141. set { this.hashValue = value; }
  5142. }
  5143. private ModuleKind kind;
  5144. /// <summary>An enumeration that indicates if the module is an executable, library or resource, and so on.</summary>
  5145. public ModuleKind Kind
  5146. {
  5147. get { return this.kind; }
  5148. set { this.kind = value; }
  5149. }
  5150. private string location;
  5151. /// <summary>The path of the file from which this module or assembly was loaded or will be stored in.</summary>
  5152. public string Location
  5153. {
  5154. get { return this.location; }
  5155. set { this.location = value; }
  5156. }
  5157. private System.Guid mvid;
  5158. public System.Guid Mvid
  5159. {
  5160. get { return this.mvid; }
  5161. set { this.mvid = value; }
  5162. }
  5163. private string targetRuntimeVersion;
  5164. /// <summary>Identifies the version of the CLR that is required to load this module or assembly.</summary>
  5165. public string TargetRuntimeVersion
  5166. {
  5167. get { return this.targetRuntimeVersion; }
  5168. set { this.targetRuntimeVersion = value; }
  5169. }
  5170. private int linkerMajorVersion = 6;
  5171. public int LinkerMajorVersion
  5172. {
  5173. get { return this.linkerMajorVersion; }
  5174. set { this.linkerMajorVersion = value; }
  5175. }
  5176. private int linkerMinorVersion;
  5177. public int LinkerMinorVersion
  5178. {
  5179. get { return this.linkerMinorVersion; }
  5180. set { this.linkerMinorVersion = value; }
  5181. }
  5182. private int metadataFormatMajorVersion;
  5183. public int MetadataFormatMajorVersion
  5184. {
  5185. get { return this.metadataFormatMajorVersion; }
  5186. set { this.metadataFormatMajorVersion = value; }
  5187. }
  5188. private int metadataFormatMinorVersion;
  5189. public int MetadataFormatMinorVersion
  5190. {
  5191. get { return this.metadataFormatMinorVersion; }
  5192. set { this.metadataFormatMinorVersion = value; }
  5193. }
  5194. private string name;
  5195. /// <summary>The name of the module or assembly. Includes the file extension if the module is not an assembly.</summary>
  5196. public string Name
  5197. {
  5198. get { return this.name; }
  5199. set { this.name = value; }
  5200. }
  5201. private PEKindFlags peKind = PEKindFlags.ILonly;
  5202. public PEKindFlags PEKind
  5203. {
  5204. get { return this.peKind; }
  5205. set { this.peKind = value; }
  5206. }
  5207. private bool trackDebugData;
  5208. public bool TrackDebugData
  5209. {
  5210. get { return this.trackDebugData; }
  5211. set { this.trackDebugData = value; }
  5212. }
  5213. private ArrayList metadataImportErrors;
  5214. /// <summary>
  5215. /// If any exceptions were encountered while reading in this module, they are recorded here. Since reading is lazy,
  5216. /// this list can grow dynamically during the use of a module.
  5217. /// </summary>
  5218. public ArrayList MetadataImportErrors
  5219. {
  5220. get { return this.metadataImportErrors; }
  5221. set { this.metadataImportErrors = value; }
  5222. }
  5223. protected AttributeList attributes;
  5224. /// <summary>
  5225. /// The attributes associated with this module or assembly. This corresponds to C# custom attributes with the assembly or module target specifier.
  5226. /// </summary>
  5227. public virtual AttributeList Attributes
  5228. {
  5229. get
  5230. {
  5231. if(this.attributes != null)
  5232. return this.attributes;
  5233. if(this.provideCustomAttributes != null)
  5234. {
  5235. lock(Module.GlobalLock)
  5236. {
  5237. if(this.attributes == null)
  5238. this.provideCustomAttributes(this);
  5239. }
  5240. }
  5241. else
  5242. this.attributes = new AttributeList();
  5243. return this.attributes;
  5244. }
  5245. set
  5246. {
  5247. this.attributes = value;
  5248. }
  5249. }
  5250. protected SecurityAttributeList securityAttributes;
  5251. /// <summary>
  5252. /// Declarative security for the module or assembly.
  5253. /// </summary>
  5254. public virtual SecurityAttributeList SecurityAttributes
  5255. {
  5256. get
  5257. {
  5258. if(this.securityAttributes != null)
  5259. return this.securityAttributes;
  5260. if(this.provideCustomAttributes != null)
  5261. {
  5262. AttributeList dummy = this.Attributes; //As a side effect, this.securityAttributes gets populated
  5263. if(dummy != null)
  5264. dummy = null;
  5265. }
  5266. else
  5267. this.securityAttributes = new SecurityAttributeList();
  5268. return this.securityAttributes;
  5269. }
  5270. set
  5271. {
  5272. this.securityAttributes = value;
  5273. }
  5274. }
  5275. /// <summary>The source code, if any, corresponding to the value in Documentation.</summary>
  5276. public Node DocumentationNode;
  5277. protected XmlDocument documentation;
  5278. /// <summary>An XML Document Object Model for a document containing all of the documentation comments applicable to members
  5279. /// defined in this module.</summary>
  5280. public virtual XmlDocument Documentation
  5281. {
  5282. get
  5283. {
  5284. XmlDocument documentation = this.documentation;
  5285. if(documentation != null)
  5286. return documentation;
  5287. if(this.DocumentationResolution != null)
  5288. documentation = this.documentation = this.DocumentationResolution(this);
  5289. if(documentation != null)
  5290. return documentation;
  5291. XmlDocument doc = null;
  5292. if(this.Directory != null && this.Name != null)
  5293. {
  5294. string fileName = this.Name + ".xml";
  5295. System.Globalization.CultureInfo cc = System.Globalization.CultureInfo.CurrentUICulture;
  5296. while(cc != null && cc != System.Globalization.CultureInfo.InvariantCulture)
  5297. {
  5298. doc = this.ProbeForXmlDocumentation(this.Directory, cc.Name, fileName);
  5299. if(doc != null)
  5300. break;
  5301. cc = cc.Parent;
  5302. }
  5303. if(doc == null)
  5304. doc = this.ProbeForXmlDocumentation(this.Directory, null, fileName);
  5305. }
  5306. if(doc == null)
  5307. doc = new XmlDocument();
  5308. return this.documentation = doc;
  5309. }
  5310. set
  5311. {
  5312. this.documentation = value;
  5313. }
  5314. }
  5315. public virtual XmlDocument ProbeForXmlDocumentation(string dir, string subDir, string fileName)
  5316. {
  5317. try
  5318. {
  5319. if(dir == null || fileName == null)
  5320. return null;
  5321. if(subDir != null)
  5322. dir = Path.Combine(dir, subDir);
  5323. string docFileName = Path.Combine(dir, fileName);
  5324. if(File.Exists(docFileName))
  5325. {
  5326. XmlDocument doc = new XmlDocument();
  5327. using(TextReader reader = File.OpenText(docFileName))
  5328. {
  5329. doc.Load(reader);
  5330. return doc;
  5331. }
  5332. }
  5333. }
  5334. catch(Exception e)
  5335. {
  5336. if(this.MetadataImportErrors == null)
  5337. this.MetadataImportErrors = new ArrayList();
  5338. this.MetadataImportErrors.Add(e);
  5339. }
  5340. return null;
  5341. }
  5342. protected internal static readonly Method NoSuchMethod = new Method();
  5343. protected Method entryPoint;
  5344. /// <summary>If this module is an executable, this method is the one that gets called to start the execution of managed code.</summary>
  5345. public virtual Method EntryPoint
  5346. {
  5347. get
  5348. {
  5349. if(this.entryPoint == null)
  5350. {
  5351. if(this.provideCustomAttributes != null)
  5352. {
  5353. AttributeList dummy = this.Attributes; //Gets the entry point as a side effect
  5354. if(dummy != null)
  5355. dummy = null;
  5356. }
  5357. else
  5358. this.entryPoint = Module.NoSuchMethod;
  5359. }
  5360. if(this.entryPoint == Module.NoSuchMethod)
  5361. return null;
  5362. return this.entryPoint;
  5363. }
  5364. set
  5365. {
  5366. this.entryPoint = value;
  5367. }
  5368. }
  5369. protected ModuleReferenceList moduleReferences;
  5370. /// <summary>The list of modules (excluding assemblies) defining members that are referred to in this module or assembly.</summary>
  5371. public ModuleReferenceList ModuleReferences
  5372. {
  5373. get
  5374. {
  5375. //Populating the type list may cause module references to be added
  5376. if(this.Types == null)
  5377. return this.moduleReferences;
  5378. return this.moduleReferences;
  5379. }
  5380. set
  5381. {
  5382. this.moduleReferences = value;
  5383. }
  5384. }
  5385. public virtual bool ContainsModule(Module module)
  5386. {
  5387. if(module == null || this.ModuleReferences == null || this.ModuleReferences.Count == 0)
  5388. return false;
  5389. int n = this.ModuleReferences.Count;
  5390. for(int i = 0; i < n; ++i)
  5391. {
  5392. ModuleReference mr = this.ModuleReferences[i];
  5393. if(mr == null)
  5394. continue;
  5395. if(mr.Module == module)
  5396. return true;
  5397. }
  5398. return false;
  5399. }
  5400. protected ResourceList resources;
  5401. /// <summary>
  5402. /// A list of managed resources linked or embedded into this module or assembly.
  5403. /// </summary>
  5404. public virtual ResourceList Resources
  5405. {
  5406. get
  5407. {
  5408. if(this.resources != null)
  5409. return this.resources;
  5410. if(this.provideResources != null)
  5411. {
  5412. lock(Module.GlobalLock)
  5413. {
  5414. if(this.resources == null)
  5415. this.provideResources(this);
  5416. }
  5417. }
  5418. else
  5419. this.resources = new ResourceList();
  5420. return this.resources;
  5421. }
  5422. set
  5423. {
  5424. this.resources = value;
  5425. }
  5426. }
  5427. protected Win32ResourceList win32Resources;
  5428. /// <summary>
  5429. /// A list of Win32 resources embedded in this module or assembly.
  5430. /// </summary>
  5431. public virtual Win32ResourceList Win32Resources
  5432. {
  5433. get
  5434. {
  5435. if(this.win32Resources != null)
  5436. return this.win32Resources;
  5437. if(this.provideResources != null)
  5438. {
  5439. ResourceList dummy = this.Resources; //gets the win32 resources as as side effect
  5440. if(dummy != null)
  5441. dummy = null;
  5442. }
  5443. else
  5444. this.win32Resources = new Win32ResourceList();
  5445. return this.win32Resources;
  5446. }
  5447. set
  5448. {
  5449. this.win32Resources = value;
  5450. }
  5451. }
  5452. /// <summary>
  5453. /// Gets the first attribute of the given type in the custom attribute list of this module. Returns null if none found.
  5454. /// This should not be called until the module has been processed to replace symbolic references
  5455. /// to members with references to the actual members.
  5456. /// </summary>
  5457. public virtual AttributeNode GetAttribute(TypeNode attributeType)
  5458. {
  5459. AttributeList attributes = this.GetAttributes(attributeType, 1);
  5460. if(attributes != null && attributes.Count > 0)
  5461. return attributes[0];
  5462. return null;
  5463. }
  5464. public virtual AttributeList GetAttributes(TypeNode attributeType)
  5465. {
  5466. return GetAttributes(attributeType, Int32.MaxValue);
  5467. }
  5468. public virtual AttributeList GetAttributes(TypeNode attributeType, int maxCount)
  5469. {
  5470. AttributeList foundAttributes = new AttributeList();
  5471. if(attributeType == null)
  5472. return foundAttributes;
  5473. AttributeList attributes = this.Attributes;
  5474. for(int i = 0, count = 0, n = attributes == null ? 0 : attributes.Count; i < n && count < maxCount; i++)
  5475. {
  5476. AttributeNode attr = attributes[i];
  5477. if(attr == null)
  5478. continue;
  5479. MemberBinding mb = attr.Constructor as MemberBinding;
  5480. if(mb != null)
  5481. {
  5482. if(mb.BoundMember == null)
  5483. continue;
  5484. if(mb.BoundMember.DeclaringType != attributeType)
  5485. continue;
  5486. foundAttributes.Add(attr);
  5487. count++;
  5488. continue;
  5489. }
  5490. Literal lit = attr.Constructor as Literal;
  5491. if(lit == null)
  5492. continue;
  5493. if((lit.Value as TypeNode) != attributeType)
  5494. continue;
  5495. foundAttributes.Add(attr);
  5496. count++;
  5497. }
  5498. return foundAttributes;
  5499. }
  5500. protected TrivialHashtable memberDocumentationCache;
  5501. public TrivialHashtable GetMemberDocumentationCache()
  5502. {
  5503. TrivialHashtable cache = this.memberDocumentationCache;
  5504. if(cache != null)
  5505. return cache;
  5506. lock(this)
  5507. {
  5508. if(this.memberDocumentationCache != null)
  5509. return this.memberDocumentationCache;
  5510. XmlDocument doc = this.Documentation;
  5511. if(doc == null && this.ContainingAssembly != null && this.ContainingAssembly != this)
  5512. return this.memberDocumentationCache = this.ContainingAssembly.memberDocumentationCache;
  5513. cache = this.memberDocumentationCache = new TrivialHashtable();
  5514. if(doc == null)
  5515. return cache;
  5516. XmlNode docElem = doc.DocumentElement;
  5517. if(docElem == null)
  5518. return cache;
  5519. XmlNode membersNode = null;
  5520. if(docElem.HasChildNodes)
  5521. {
  5522. foreach(XmlNode dec in docElem.ChildNodes)
  5523. if(dec.Name == "members") { membersNode = dec; break; }
  5524. }
  5525. if(membersNode == null)
  5526. return cache;
  5527. if(membersNode.HasChildNodes)
  5528. {
  5529. foreach(XmlNode member in membersNode.ChildNodes)
  5530. {
  5531. if(member.Name != "member")
  5532. continue;
  5533. XmlNode nameAttr = member.Attributes.GetNamedItem("name");
  5534. if(nameAttr == null)
  5535. continue;
  5536. cache[Identifier.For(nameAttr.Value).UniqueIdKey] = member;
  5537. }
  5538. }
  5539. return cache;
  5540. }
  5541. }
  5542. protected TrivialHashtable validNamespaces;
  5543. public NamespaceList GetNamespaceList()
  5544. {
  5545. if(this.reader != null)
  5546. return this.GetNamespaceListFromReader();
  5547. TypeNodeList types = this.Types;
  5548. int n = types == null ? 0 : types.Count;
  5549. if(this.namespaceList == null || n > this.savedTypesLength)
  5550. {
  5551. lock(this)
  5552. {
  5553. if(this.namespaceList != null && this.types != null && this.types.Count == this.savedTypesLength)
  5554. return this.namespaceList;
  5555. NamespaceList nsList = this.namespaceList = new NamespaceList();
  5556. TrivialHashtable nsTable = this.validNamespaces = new TrivialHashtable();
  5557. for(int i = 0; i < n; i++)
  5558. {
  5559. //^ assert this.types != null;
  5560. TypeNode t = this.types[i];
  5561. if(t == null)
  5562. continue;
  5563. if(t.Namespace == null)
  5564. t.Namespace = Identifier.Empty;
  5565. Namespace ns = nsTable[t.Namespace.UniqueIdKey] as Namespace;
  5566. if(ns != null)
  5567. {
  5568. if(t.IsPublic)
  5569. ns.isPublic = true;
  5570. ns.Types.Add(t);
  5571. continue;
  5572. }
  5573. ns = new Namespace(t.Namespace);
  5574. ns.isPublic = t.IsPublic;
  5575. ns.Types = new TypeNodeList();
  5576. ns.Types.Add(t);
  5577. nsTable[t.Namespace.UniqueIdKey] = ns;
  5578. nsList.Add(ns);
  5579. }
  5580. }
  5581. }
  5582. return this.namespaceList;
  5583. }
  5584. private NamespaceList GetNamespaceListFromReader()
  5585. //^ requires this.reader != null;
  5586. {
  5587. if(this.namespaceList == null)
  5588. {
  5589. lock(Module.GlobalLock)
  5590. {
  5591. this.reader.GetNamespaces();
  5592. NamespaceList nsList = this.namespaceList = this.reader.namespaceList;
  5593. TrivialHashtable nsTable = this.validNamespaces = new TrivialHashtable();
  5594. for(int i = 0, n = nsList == null ? 0 : nsList.Count; i < n; i++)
  5595. {
  5596. //^ assert nsList != null;
  5597. Namespace ns = nsList[i];
  5598. if(ns == null || ns.Name == null)
  5599. continue;
  5600. ns.ProvideTypes = new Namespace.TypeProvider(this.GetTypesForNamespace);
  5601. nsTable[ns.Name.UniqueIdKey] = ns;
  5602. }
  5603. }
  5604. }
  5605. return this.namespaceList;
  5606. }
  5607. private void GetTypesForNamespace(Namespace nspace, object handle)
  5608. {
  5609. if(nspace == null || nspace.Name == null)
  5610. return;
  5611. lock(Module.GlobalLock)
  5612. {
  5613. int key = nspace.Name.UniqueIdKey;
  5614. TypeNodeList types = this.Types;
  5615. TypeNodeList nsTypes = nspace.Types = new TypeNodeList();
  5616. for(int i = 0, n = types == null ? 0 : types.Count; i < n; i++)
  5617. {
  5618. TypeNode t = types[i];
  5619. if(t == null || t.Namespace == null)
  5620. continue;
  5621. if(t.Namespace.UniqueIdKey == key)
  5622. nsTypes.Add(t);
  5623. }
  5624. }
  5625. }
  5626. public bool IsValidNamespace(Identifier nsName)
  5627. {
  5628. if(nsName == null)
  5629. return false;
  5630. this.GetNamespaceList();
  5631. //^ assert this.validNamespaces != null;
  5632. return this.validNamespaces[nsName.UniqueIdKey] != null;
  5633. }
  5634. public bool IsValidTypeName(Identifier nsName, Identifier typeName)
  5635. {
  5636. if(nsName == null || typeName == null)
  5637. return false;
  5638. if(!this.IsValidNamespace(nsName))
  5639. return false;
  5640. if(this.reader != null)
  5641. return this.reader.IsValidTypeName(nsName, typeName);
  5642. return this.GetType(nsName, typeName) != null;
  5643. }
  5644. public Module GetNestedModule(string moduleName)
  5645. {
  5646. if(this.Types == null) { Debug.Assert(false); } //Just get the types to pull in any exported types
  5647. ModuleReferenceList moduleReferences = this.ModuleReferences; //This should now contain all interesting referenced modules
  5648. for(int i = 0, n = moduleReferences == null ? 0 : moduleReferences.Count; i < n; i++)
  5649. {
  5650. ModuleReference mref = moduleReferences[i];
  5651. if(mref == null)
  5652. continue;
  5653. if(mref.Name == moduleName)
  5654. return mref.Module;
  5655. }
  5656. return null;
  5657. }
  5658. internal TrivialHashtableUsingWeakReferences/*!*/ StructurallyEquivalentType
  5659. {
  5660. get
  5661. {
  5662. if(this.structurallyEquivalentType == null)
  5663. this.structurallyEquivalentType = new TrivialHashtableUsingWeakReferences();
  5664. return this.structurallyEquivalentType;
  5665. }
  5666. }
  5667. private TrivialHashtableUsingWeakReferences structurallyEquivalentType;
  5668. /// <summary>
  5669. /// The identifier represents the structure via some mangling scheme. The result can be either from this module,
  5670. /// or any module this module has a reference to.
  5671. /// </summary>
  5672. public virtual TypeNode GetStructurallyEquivalentType(Identifier ns, Identifier/*!*/ id)
  5673. {
  5674. return this.GetStructurallyEquivalentType(ns, id, id, true);
  5675. }
  5676. public virtual TypeNode GetStructurallyEquivalentType(Identifier ns, Identifier/*!*/ id, Identifier uniqueMangledName, bool lookInReferencedAssemblies)
  5677. {
  5678. if(uniqueMangledName == null)
  5679. uniqueMangledName = id;
  5680. TypeNode result = (TypeNode)this.StructurallyEquivalentType[uniqueMangledName.UniqueIdKey];
  5681. if(result == Class.DoesNotExist)
  5682. return null;
  5683. if(result != null)
  5684. return result;
  5685. lock(Module.GlobalLock)
  5686. {
  5687. result = this.GetType(ns, id);
  5688. if(result != null)
  5689. {
  5690. this.StructurallyEquivalentType[uniqueMangledName.UniqueIdKey] = result;
  5691. return result;
  5692. }
  5693. if(!lookInReferencedAssemblies)
  5694. goto notfound;
  5695. AssemblyReferenceList refs = this.AssemblyReferences;
  5696. for(int i = 0, n = refs == null ? 0 : refs.Count; i < n; i++)
  5697. {
  5698. AssemblyReference ar = refs[i];
  5699. if(ar == null)
  5700. continue;
  5701. AssemblyNode a = ar.Assembly;
  5702. if(a == null)
  5703. continue;
  5704. result = a.GetType(ns, id);
  5705. if(result != null)
  5706. {
  5707. this.StructurallyEquivalentType[uniqueMangledName.UniqueIdKey] = result;
  5708. return result;
  5709. }
  5710. }
  5711. notfound:
  5712. this.StructurallyEquivalentType[uniqueMangledName.UniqueIdKey] = Class.DoesNotExist;
  5713. return null;
  5714. }
  5715. }
  5716. public virtual TypeNode GetType(Identifier @namespace, Identifier name, bool lookInReferencedAssemblies)
  5717. {
  5718. return this.GetType(@namespace, name, lookInReferencedAssemblies, lookInReferencedAssemblies ? new TrivialHashtable() : null);
  5719. }
  5720. protected virtual TypeNode GetType(Identifier @namespace, Identifier name, bool lookInReferencedAssemblies, TrivialHashtable assembliesAlreadyVisited)
  5721. {
  5722. if(assembliesAlreadyVisited != null)
  5723. {
  5724. if(assembliesAlreadyVisited[this.UniqueKey] != null)
  5725. return null;
  5726. assembliesAlreadyVisited[this.UniqueKey] = this;
  5727. }
  5728. TypeNode result = this.GetType(@namespace, name);
  5729. if(result != null || !lookInReferencedAssemblies)
  5730. return result;
  5731. AssemblyReferenceList refs = this.AssemblyReferences;
  5732. for(int i = 0, n = refs == null ? 0 : refs.Count; i < n; i++)
  5733. {
  5734. AssemblyReference ar = refs[i];
  5735. if(ar == null)
  5736. continue;
  5737. AssemblyNode a = ar.Assembly;
  5738. if(a == null)
  5739. continue;
  5740. result = a.GetType(@namespace, name, true, assembliesAlreadyVisited);
  5741. if(result != null)
  5742. return result;
  5743. }
  5744. return null;
  5745. }
  5746. public virtual TypeNode GetType(Identifier @namespace, Identifier name)
  5747. {
  5748. if(@namespace == null || name == null)
  5749. return null;
  5750. TypeNode result = null;
  5751. if(this.namespaceTable == null)
  5752. this.namespaceTable = new TrivialHashtable();
  5753. TrivialHashtable nsTable = (TrivialHashtable)this.namespaceTable[@namespace.UniqueIdKey];
  5754. if(nsTable != null)
  5755. {
  5756. result = (TypeNode)nsTable[name.UniqueIdKey];
  5757. if(result == Class.DoesNotExist)
  5758. return null;
  5759. if(result != null)
  5760. return result;
  5761. }
  5762. else
  5763. {
  5764. lock(Module.GlobalLock)
  5765. {
  5766. nsTable = (TrivialHashtable)this.namespaceTable[@namespace.UniqueIdKey];
  5767. if(nsTable == null)
  5768. this.namespaceTable[@namespace.UniqueIdKey] = nsTable = new TrivialHashtable(32);
  5769. }
  5770. }
  5771. if(this.provideTypeNode != null)
  5772. {
  5773. lock(Module.GlobalLock)
  5774. {
  5775. result = (TypeNode)nsTable[name.UniqueIdKey];
  5776. if(result == Class.DoesNotExist)
  5777. return null;
  5778. if(result != null)
  5779. return result;
  5780. result = this.provideTypeNode(@namespace, name);
  5781. if(result != null)
  5782. {
  5783. nsTable[name.UniqueIdKey] = result;
  5784. return result;
  5785. }
  5786. // !EFW - Removed by ComponentOne
  5787. //nsTable[name.UniqueIdKey] = Class.DoesNotExist;
  5788. return null;
  5789. }
  5790. }
  5791. if(this.types != null && this.types.Count > this.savedTypesLength)
  5792. {
  5793. int n = this.savedTypesLength = this.types.Count;
  5794. for(int i = 0; i < n; i++)
  5795. {
  5796. TypeNode t = this.types[i];
  5797. if(t == null)
  5798. continue;
  5799. if(t.Namespace == null)
  5800. t.Namespace = Identifier.Empty;
  5801. nsTable = (TrivialHashtable)this.namespaceTable[t.Namespace.UniqueIdKey];
  5802. if(nsTable == null)
  5803. this.namespaceTable[t.Namespace.UniqueIdKey] = nsTable = new TrivialHashtable();
  5804. nsTable[t.Name.UniqueIdKey] = t;
  5805. }
  5806. return this.GetType(@namespace, name);
  5807. }
  5808. return null;
  5809. }
  5810. protected internal TypeNodeList types;
  5811. /// <summary>The types contained in this module or assembly.</summary>
  5812. public virtual TypeNodeList Types
  5813. {
  5814. get
  5815. {
  5816. if(this.types != null)
  5817. return this.types;
  5818. if(this.provideTypeNodeList != null)
  5819. {
  5820. lock(Module.GlobalLock)
  5821. {
  5822. if(this.types == null)
  5823. this.provideTypeNodeList(this);
  5824. }
  5825. }
  5826. else
  5827. this.types = new TypeNodeList();
  5828. return this.types;
  5829. }
  5830. set
  5831. {
  5832. this.types = value;
  5833. }
  5834. }
  5835. protected TrivialHashtable referencedModulesAndAssemblies;
  5836. public virtual bool HasReferenceTo(Module module)
  5837. {
  5838. if(module == null)
  5839. return false;
  5840. AssemblyNode assembly = module as AssemblyNode;
  5841. if(assembly != null)
  5842. {
  5843. AssemblyReferenceList arefs = this.AssemblyReferences;
  5844. for(int i = 0, n = arefs == null ? 0 : arefs.Count; i < n; i++)
  5845. {
  5846. AssemblyReference aref = arefs[i];
  5847. if(aref == null)
  5848. continue;
  5849. if(aref.Matches(assembly.Name, assembly.Version, assembly.Culture, assembly.PublicKeyToken))
  5850. return true;
  5851. }
  5852. }
  5853. if(this.ContainingAssembly != module.ContainingAssembly)
  5854. return false;
  5855. ModuleReferenceList mrefs = this.ModuleReferences;
  5856. for(int i = 0, n = mrefs == null ? 0 : mrefs.Count; i < n; i++)
  5857. {
  5858. //^ assert mrefs != null;
  5859. ModuleReference mref = mrefs[i];
  5860. if(mref == null || mref.Name == null)
  5861. continue;
  5862. if(0 == PlatformHelpers.StringCompareOrdinalIgnoreCase(mref.Name, module.Name))
  5863. return true;
  5864. }
  5865. return false;
  5866. }
  5867. internal void InitializeAssemblyReferenceResolution(Module referringModule)
  5868. {
  5869. if(this.AssemblyReferenceResolution == null && referringModule != null)
  5870. {
  5871. this.AssemblyReferenceResolution = referringModule.AssemblyReferenceResolution;
  5872. this.AssemblyReferenceResolutionAfterProbingFailed = referringModule.AssemblyReferenceResolutionAfterProbingFailed;
  5873. }
  5874. }
  5875. public static Module GetModule(byte[] buffer)
  5876. {
  5877. return Module.GetModule(buffer, null, false, false, true, false);
  5878. }
  5879. public static Module GetModule(byte[] buffer, IDictionary cache)
  5880. {
  5881. return Module.GetModule(buffer, null, false, false, false, false);
  5882. }
  5883. public static Module GetModule(byte[] buffer, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache)
  5884. {
  5885. return Module.GetModule(buffer, cache, doNotLockFile, getDebugInfo, useGlobalCache, false);
  5886. }
  5887. public static Module GetModule(byte[] buffer, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches)
  5888. {
  5889. if(buffer == null)
  5890. return null;
  5891. return (new Reader(buffer, cache, doNotLockFile, getDebugInfo, useGlobalCache, false)).ReadModule();
  5892. }
  5893. public static Module GetModule(string location)
  5894. {
  5895. return Module.GetModule(location, null, false, false, true, false);
  5896. }
  5897. public static Module GetModule(string location, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache)
  5898. {
  5899. return Module.GetModule(location, null, doNotLockFile, getDebugInfo, useGlobalCache, false);
  5900. }
  5901. public static Module GetModule(string location, IDictionary cache)
  5902. {
  5903. return Module.GetModule(location, cache, false, false, false, false);
  5904. }
  5905. public static Module GetModule(string location, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache)
  5906. {
  5907. return Module.GetModule(location, cache, doNotLockFile, getDebugInfo, useGlobalCache, false);
  5908. }
  5909. public static Module GetModule(string location, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches)
  5910. {
  5911. if(location == null)
  5912. return null;
  5913. return (new Reader(location, cache, doNotLockFile, getDebugInfo, useGlobalCache, preserveShortBranches)).ReadModule();
  5914. }
  5915. public virtual AssemblyNode Resolve(AssemblyReference assemblyReference)
  5916. {
  5917. if(this.AssemblyReferenceResolution == null)
  5918. return null;
  5919. return this.AssemblyReferenceResolution(assemblyReference, this);
  5920. }
  5921. public virtual AssemblyNode ResolveAfterProbingFailed(AssemblyReference assemblyReference)
  5922. {
  5923. if(this.AssemblyReferenceResolutionAfterProbingFailed == null)
  5924. return null;
  5925. return this.AssemblyReferenceResolutionAfterProbingFailed(assemblyReference, this);
  5926. }
  5927. public virtual void AfterAssemblyLoadProcessing()
  5928. {
  5929. if(this.AfterAssemblyLoad != null)
  5930. {
  5931. this.AfterAssemblyLoad(this as AssemblyNode);
  5932. }
  5933. }
  5934. public virtual void WriteDocumentation(System.IO.TextWriter doc)
  5935. {
  5936. if(this.documentation == null)
  5937. return;
  5938. XmlTextWriter xwriter = new XmlTextWriter(doc);
  5939. xwriter.Formatting = Formatting.Indented;
  5940. xwriter.Indentation = 2;
  5941. xwriter.WriteProcessingInstruction("xml", "version=\"1.0\"");
  5942. xwriter.WriteStartElement("doc");
  5943. AssemblyNode assem = this as AssemblyNode;
  5944. if(assem != null)
  5945. {
  5946. xwriter.WriteStartElement("assembly");
  5947. xwriter.WriteElementString("name", assem.Name);
  5948. xwriter.WriteEndElement();
  5949. }
  5950. xwriter.WriteStartElement("members");
  5951. TypeNodeList types = this.Types;
  5952. for(int i = 1, n = types == null ? 0 : types.Count; i < n; i++)
  5953. {
  5954. //^ assert types != null;
  5955. TypeNode t = types[i];
  5956. if(t == null)
  5957. continue;
  5958. t.WriteDocumentation(xwriter);
  5959. }
  5960. xwriter.WriteEndElement();
  5961. xwriter.WriteEndElement();
  5962. xwriter.Close();
  5963. }
  5964. }
  5965. // An assembly is a module with a strong name
  5966. public class AssemblyNode : Module
  5967. {
  5968. private static Hashtable CompiledAssemblies;// so we can find in-memory compiled assemblies later (contains weak references)
  5969. protected AssemblyNode contractAssembly;
  5970. /// <summary>A separate assembly that supplied the type and method contracts for this assembly.</summary>
  5971. public virtual AssemblyNode ContractAssembly
  5972. {
  5973. get
  5974. {
  5975. return this.contractAssembly;
  5976. }
  5977. set
  5978. {
  5979. if(this.contractAssembly != null)
  5980. {
  5981. Debug.Assert(false);
  5982. return;
  5983. }
  5984. this.contractAssembly = value;
  5985. if(value == null)
  5986. return;
  5987. #region Copy over any external references from the contract assembly to this one (if needed)
  5988. // These external references are needed only for the contract deserializer
  5989. AssemblyReferenceList ars = new AssemblyReferenceList();
  5990. AssemblyReferenceList contractReferences = value.AssemblyReferences;
  5991. // see if contractReferences[i] is already in the external references of "this"
  5992. for(int i = 0, n = contractReferences == null ? 0 : contractReferences.Count; i < n; i++)
  5993. {
  5994. //^ assert contractReferences != null;
  5995. AssemblyReference aref = contractReferences[i];
  5996. if(aref == null)
  5997. continue;
  5998. if(aref.Assembly != this)
  5999. { // don't copy the contract's external reference to "this"
  6000. int j = 0;
  6001. int m = this.AssemblyReferences == null ? 0 : this.AssemblyReferences.Count;
  6002. while(j < m)
  6003. {
  6004. if(aref.Assembly.Name != null &&
  6005. this.AssemblyReferences[j].Name != null &&
  6006. aref.Assembly.Name.Equals(this.AssemblyReferences[j].Name))
  6007. break;
  6008. j++;
  6009. }
  6010. if(j == m)
  6011. { // then it wasn't found in the list of the real references
  6012. ars.Add(contractReferences[i]);
  6013. }
  6014. }
  6015. }
  6016. if(this.AssemblyReferences == null)
  6017. this.AssemblyReferences = new AssemblyReferenceList(ars);
  6018. else
  6019. this.AssemblyReferences.AddRange(ars);
  6020. #endregion Copy over any external references from the contract assembly to this one (if needed)
  6021. TypeNodeList instantiatedTypes = null;
  6022. if(this.reader != null)
  6023. instantiatedTypes = this.reader.GetInstantiatedTypes();
  6024. if(instantiatedTypes != null)
  6025. for(int i = 0, n = instantiatedTypes.Count; i < n; i++)
  6026. {
  6027. TypeNode t = instantiatedTypes[i];
  6028. if(t == null)
  6029. continue;
  6030. if(t.members == null)
  6031. continue;
  6032. }
  6033. }
  6034. }
  6035. internal static readonly AssemblyNode/*!*/ Dummy = new AssemblyNode();
  6036. protected string strongName;
  6037. /// <summary>
  6038. /// A string containing the name, version, culture and key of this assembly, formatted as required by the CLR loader.
  6039. /// </summary>
  6040. public virtual string/*!*/ StrongName
  6041. {
  6042. get
  6043. {
  6044. if(this.strongName == null)
  6045. this.strongName = AssemblyNode.GetStrongName(this.Name, this.Version, this.Culture, this.PublicKeyOrToken, (this.Flags & AssemblyFlags.Retargetable) != 0);
  6046. return this.strongName;
  6047. }
  6048. }
  6049. [Obsolete("Please use GetAttribute(TypeNode attributeType)")]
  6050. public virtual AttributeNode GetAttributeByName(TypeNode attributeType)
  6051. {
  6052. if(attributeType == null)
  6053. return null;
  6054. AttributeList attributes = this.Attributes;
  6055. for(int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++)
  6056. {
  6057. //^ assert attributes != null;
  6058. AttributeNode attr = attributes[i];
  6059. if(attr == null)
  6060. continue;
  6061. MemberBinding mb = attr.Constructor as MemberBinding;
  6062. if(mb != null)
  6063. {
  6064. if(mb.BoundMember == null || mb.BoundMember.DeclaringType == null)
  6065. continue;
  6066. if(mb.BoundMember.DeclaringType.FullName != attributeType.FullName)
  6067. continue;
  6068. return attr;
  6069. }
  6070. }
  6071. return null;
  6072. }
  6073. /// <summary>
  6074. /// Gets the first attribute of the given type in the custom attribute list of this member. Returns null if none found.
  6075. /// The member is assumed to be either imported, or already in a form suitable for export.
  6076. /// </summary>
  6077. public virtual AttributeNode GetModuleAttribute(TypeNode attributeType)
  6078. {
  6079. if(attributeType == null)
  6080. return null;
  6081. AttributeList attributes = this.ModuleAttributes;
  6082. for(int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++)
  6083. {
  6084. //^ assert attributes != null;
  6085. AttributeNode attr = attributes[i];
  6086. if(attr == null)
  6087. continue;
  6088. MemberBinding mb = attr.Constructor as MemberBinding;
  6089. if(mb != null)
  6090. {
  6091. if(mb.BoundMember == null)
  6092. continue;
  6093. if(mb.BoundMember.DeclaringType != attributeType)
  6094. continue;
  6095. return attr;
  6096. }
  6097. Literal lit = attr.Constructor as Literal;
  6098. if(lit == null)
  6099. continue;
  6100. if((lit.Value as TypeNode) != attributeType)
  6101. continue;
  6102. return attr;
  6103. }
  6104. return null;
  6105. }
  6106. public AssemblyNode()
  6107. : base()
  6108. {
  6109. this.NodeType = NodeType.Assembly;
  6110. this.ContainingAssembly = this;
  6111. }
  6112. public AssemblyNode(TypeNodeProvider provider, TypeNodeListProvider listProvider,
  6113. CustomAttributeProvider provideCustomAttributes, ResourceProvider provideResources, string directory)
  6114. : base(provider, listProvider, provideCustomAttributes, provideResources)
  6115. {
  6116. this.Directory = directory;
  6117. this.NodeType = NodeType.Assembly;
  6118. this.ContainingAssembly = this;
  6119. }
  6120. public override void Dispose()
  6121. {
  6122. if(this.cachedRuntimeAssembly != null)
  6123. this.cachedRuntimeAssembly.Dispose();
  6124. this.cachedRuntimeAssembly = null;
  6125. lock(Reader.StaticAssemblyCache)
  6126. {
  6127. foreach(object key in new ArrayList(Reader.StaticAssemblyCache.Keys))
  6128. {
  6129. if(Reader.StaticAssemblyCache[key] == this)
  6130. Reader.StaticAssemblyCache.Remove(key);
  6131. }
  6132. AssemblyReference aRef = (AssemblyReference)TargetPlatform.AssemblyReferenceFor[Identifier.For(this.Name).UniqueIdKey];
  6133. if(aRef != null && aRef.Assembly == this)
  6134. {
  6135. aRef.Assembly = null;
  6136. //TODO: what about other static references to the assembly, such as SystemTypes.SystemXmlAssembly?
  6137. }
  6138. }
  6139. base.Dispose();
  6140. }
  6141. private string culture;
  6142. /// <summary>The target culture of any localized resources in this assembly.</summary>
  6143. public string Culture
  6144. {
  6145. get { return this.culture; }
  6146. set { this.culture = value; }
  6147. }
  6148. private AssemblyFlags flags;
  6149. /// <summary>An enumeration that identifies the what kind of assembly this is.</summary>
  6150. public AssemblyFlags Flags
  6151. {
  6152. get { return this.flags; }
  6153. set { this.flags = value; }
  6154. }
  6155. private string moduleName;
  6156. /// <summary>Attributes that specifically target a module rather an assembly.</summary>
  6157. public string ModuleName
  6158. { //An assembly can have a different name from the module.
  6159. get { return this.moduleName; }
  6160. set { this.moduleName = value; }
  6161. }
  6162. private byte[] publicKeyOrToken;
  6163. /// <summary>The public part of the key pair used to sign this assembly, or a hash of the public key.</summary>
  6164. public byte[] PublicKeyOrToken
  6165. {
  6166. get { return this.publicKeyOrToken; }
  6167. set { this.publicKeyOrToken = value; }
  6168. }
  6169. private System.Version version;
  6170. /// <summary>The version of this assembly.</summary>
  6171. public System.Version Version
  6172. {
  6173. get { return this.version; }
  6174. set { this.version = value; }
  6175. }
  6176. private DateTime fileLastWriteTimeUtc;
  6177. public DateTime FileLastWriteTimeUtc
  6178. {
  6179. get { return this.fileLastWriteTimeUtc; }
  6180. set { this.fileLastWriteTimeUtc = value; }
  6181. }
  6182. protected TypeNodeList exportedTypes;
  6183. /// <summary>
  6184. /// Public types defined in other modules making up this assembly and to which other assemblies may refer to.
  6185. /// </summary>
  6186. public virtual TypeNodeList ExportedTypes
  6187. {
  6188. get
  6189. {
  6190. if(this.exportedTypes != null)
  6191. return this.exportedTypes;
  6192. if(this.provideTypeNodeList != null)
  6193. {
  6194. TypeNodeList types = this.Types; //Gets the exported types as a side-effect
  6195. if(types != null)
  6196. types = null;
  6197. }
  6198. else
  6199. this.exportedTypes = new TypeNodeList();
  6200. return this.exportedTypes;
  6201. }
  6202. set
  6203. {
  6204. this.exportedTypes = value;
  6205. }
  6206. }
  6207. public bool GetDebugSymbols
  6208. {
  6209. get
  6210. {
  6211. if(this.reader == null)
  6212. return false;
  6213. return this.reader.getDebugSymbols;
  6214. }
  6215. set
  6216. {
  6217. if(this.reader == null)
  6218. return;
  6219. this.reader.getDebugSymbols = value;
  6220. }
  6221. }
  6222. public static AssemblyNode GetAssembly(byte[] buffer)
  6223. {
  6224. return AssemblyNode.GetAssembly(buffer, null, false, false, true, false);
  6225. }
  6226. public static AssemblyNode GetAssembly(byte[] buffer, IDictionary cache)
  6227. {
  6228. return AssemblyNode.GetAssembly(buffer, cache, false, false, false, false);
  6229. }
  6230. public static AssemblyNode GetAssembly(byte[] buffer, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache)
  6231. {
  6232. return AssemblyNode.GetAssembly(buffer, cache, doNotLockFile, getDebugInfo, useGlobalCache, false);
  6233. }
  6234. public static AssemblyNode GetAssembly(byte[] buffer, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches)
  6235. {
  6236. if(buffer == null)
  6237. return null;
  6238. if(CoreSystemTypes.SystemAssembly == null)
  6239. Debug.Fail("");
  6240. return (new Reader(buffer, cache, doNotLockFile, getDebugInfo, useGlobalCache, preserveShortBranches)).ReadModule() as AssemblyNode;
  6241. }
  6242. public static AssemblyNode GetAssembly(string location)
  6243. {
  6244. return AssemblyNode.GetAssembly(location, null, false, false, true, false);
  6245. }
  6246. public static AssemblyNode GetAssembly(string location, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache)
  6247. {
  6248. return AssemblyNode.GetAssembly(location, null, doNotLockFile, getDebugInfo, useGlobalCache, false);
  6249. }
  6250. public static AssemblyNode GetAssembly(string location, IDictionary cache)
  6251. {
  6252. return AssemblyNode.GetAssembly(location, cache, false, false, false, false);
  6253. }
  6254. public static AssemblyNode GetAssembly(string location, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache)
  6255. {
  6256. return AssemblyNode.GetAssembly(location, cache, doNotLockFile, getDebugInfo, useGlobalCache, false);
  6257. }
  6258. public static AssemblyNode GetAssembly(string location, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches)
  6259. {
  6260. if(location == null)
  6261. return null;
  6262. if(CoreSystemTypes.SystemAssembly == null)
  6263. Debug.Fail("");
  6264. return (new Reader(location, cache, doNotLockFile, getDebugInfo, useGlobalCache, preserveShortBranches)).ReadModule() as AssemblyNode;
  6265. }
  6266. public static AssemblyNode GetAssembly(AssemblyReference assemblyReference)
  6267. {
  6268. return AssemblyNode.GetAssembly(assemblyReference, null, false, false, true, false);
  6269. }
  6270. public static AssemblyNode GetAssembly(AssemblyReference assemblyReference, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache)
  6271. {
  6272. return AssemblyNode.GetAssembly(assemblyReference, null, doNotLockFile, getDebugInfo, useGlobalCache, false);
  6273. }
  6274. public static AssemblyNode GetAssembly(AssemblyReference assemblyReference, IDictionary cache)
  6275. {
  6276. return AssemblyNode.GetAssembly(assemblyReference, cache, false, false, false, false);
  6277. }
  6278. public static AssemblyNode GetAssembly(AssemblyReference assemblyReference, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache)
  6279. {
  6280. return AssemblyNode.GetAssembly(assemblyReference, cache, doNotLockFile, getDebugInfo, useGlobalCache, false);
  6281. }
  6282. public static AssemblyNode GetAssembly(AssemblyReference assemblyReference, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches)
  6283. {
  6284. if(assemblyReference == null)
  6285. return null;
  6286. if(CoreSystemTypes.SystemAssembly == null)
  6287. Debug.Fail("");
  6288. Reader reader = new Reader(cache, doNotLockFile, getDebugInfo, useGlobalCache, preserveShortBranches);
  6289. return assemblyReference.Assembly = reader.GetAssemblyFromReference(assemblyReference);
  6290. }
  6291. public static AssemblyNode GetAssembly(System.Reflection.Assembly runtimeAssembly)
  6292. {
  6293. return AssemblyNode.GetAssembly(runtimeAssembly, null, false, true, false);
  6294. }
  6295. public static AssemblyNode GetAssembly(System.Reflection.Assembly runtimeAssembly, IDictionary cache)
  6296. {
  6297. return AssemblyNode.GetAssembly(runtimeAssembly, cache, false, false, false);
  6298. }
  6299. public static AssemblyNode GetAssembly(System.Reflection.Assembly runtimeAssembly, IDictionary cache, bool getDebugInfo, bool useGlobalCache)
  6300. {
  6301. return AssemblyNode.GetAssembly(runtimeAssembly, cache, getDebugInfo, useGlobalCache, false);
  6302. }
  6303. public static AssemblyNode GetAssembly(System.Reflection.Assembly runtimeAssembly, IDictionary cache, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches)
  6304. {
  6305. if(runtimeAssembly == null)
  6306. return null;
  6307. if(CoreSystemTypes.SystemAssembly == null)
  6308. Debug.Fail("");
  6309. if(runtimeAssembly.GetName().Name == "mscorlib")
  6310. {
  6311. return CoreSystemTypes.SystemAssembly;
  6312. }
  6313. if(AssemblyNode.CompiledAssemblies != null)
  6314. {
  6315. WeakReference weakRef = (WeakReference)AssemblyNode.CompiledAssemblies[runtimeAssembly];
  6316. if(weakRef != null)
  6317. {
  6318. AssemblyNode assem = (AssemblyNode)weakRef.Target;
  6319. if(assem == null)
  6320. AssemblyNode.CompiledAssemblies.Remove(runtimeAssembly); //Remove the dead WeakReference
  6321. return assem;
  6322. }
  6323. }
  6324. if(runtimeAssembly.Location != null && runtimeAssembly.Location.Length > 0)
  6325. return AssemblyNode.GetAssembly(runtimeAssembly.Location, cache, false, getDebugInfo, useGlobalCache, preserveShortBranches);
  6326. //Get here for in memory assemblies that were not loaded from a known AssemblyNode
  6327. //Need CLR support to handle such assemblies. For now return null.
  6328. return null;
  6329. }
  6330. public void SetupDebugReader(string pdbSearchPath)
  6331. {
  6332. if(this.reader == null) { Debug.Assert(false); return; }
  6333. this.reader.SetupDebugReader(this.Location, pdbSearchPath);
  6334. }
  6335. internal static string/*!*/ GetStrongName(string name, Version version, string culture, byte[] publicKey, bool retargetable)
  6336. {
  6337. if(version == null)
  6338. version = new Version();
  6339. StringBuilder result = new StringBuilder();
  6340. result.Append(name);
  6341. result.Append(", Version=");
  6342. result.Append(version.ToString());
  6343. result.Append(", Culture=");
  6344. result.Append(((culture == null || culture.Length == 0) ? "neutral" : culture));
  6345. result.Append(AssemblyNode.GetKeyString(publicKey));
  6346. if(retargetable)
  6347. result.Append(", Retargetable=Yes");
  6348. return result.ToString();
  6349. }
  6350. private System.Reflection.AssemblyName assemblyName;
  6351. public System.Reflection.AssemblyName GetAssemblyName()
  6352. {
  6353. if(this.assemblyName == null)
  6354. {
  6355. System.Reflection.AssemblyName aName = new System.Reflection.AssemblyName();
  6356. if(this.Location != null && this.Location != "unknown:location")
  6357. {
  6358. StringBuilder sb = new StringBuilder("file:///");
  6359. sb.Append(Path.GetFullPath(this.Location));
  6360. sb.Replace('\\', '/');
  6361. aName.CodeBase = sb.ToString();
  6362. }
  6363. aName.CultureInfo = new System.Globalization.CultureInfo(this.Culture);
  6364. if(this.PublicKeyOrToken != null && this.PublicKeyOrToken.Length > 8)
  6365. aName.Flags = System.Reflection.AssemblyNameFlags.PublicKey;
  6366. if((this.Flags & AssemblyFlags.Retargetable) != 0)
  6367. aName.Flags |= (System.Reflection.AssemblyNameFlags)AssemblyFlags.Retargetable;
  6368. aName.HashAlgorithm = (System.Configuration.Assemblies.AssemblyHashAlgorithm)this.HashAlgorithm;
  6369. if(this.PublicKeyOrToken != null && this.PublicKeyOrToken.Length > 0)
  6370. aName.SetPublicKey(this.PublicKeyOrToken);
  6371. else
  6372. aName.SetPublicKey(new byte[0]);
  6373. aName.Name = this.Name;
  6374. aName.Version = this.Version;
  6375. switch(this.Flags & AssemblyFlags.CompatibilityMask)
  6376. {
  6377. case AssemblyFlags.NonSideBySideCompatible:
  6378. aName.VersionCompatibility = System.Configuration.Assemblies.AssemblyVersionCompatibility.SameDomain;
  6379. break;
  6380. case AssemblyFlags.NonSideBySideProcess:
  6381. aName.VersionCompatibility = System.Configuration.Assemblies.AssemblyVersionCompatibility.SameProcess;
  6382. break;
  6383. case AssemblyFlags.NonSideBySideMachine:
  6384. aName.VersionCompatibility = System.Configuration.Assemblies.AssemblyVersionCompatibility.SameMachine;
  6385. break;
  6386. }
  6387. this.assemblyName = aName;
  6388. }
  6389. return this.assemblyName;
  6390. }
  6391. private sealed class CachedRuntimeAssembly : IDisposable
  6392. {
  6393. internal System.Reflection.Assembly Value;
  6394. internal CachedRuntimeAssembly(System.Reflection.Assembly assembly)
  6395. {
  6396. this.Value = assembly;
  6397. }
  6398. ~CachedRuntimeAssembly()
  6399. {
  6400. this.Dispose();
  6401. }
  6402. public void Dispose()
  6403. {
  6404. if(this.Value != null)
  6405. {
  6406. if(AssemblyNode.CompiledAssemblies != null)
  6407. AssemblyNode.CompiledAssemblies.Remove(this.Value);
  6408. }
  6409. this.Value = null;
  6410. GC.SuppressFinalize(this);
  6411. }
  6412. }
  6413. private CachedRuntimeAssembly cachedRuntimeAssembly;
  6414. public System.Reflection.Assembly GetRuntimeAssembly()
  6415. {
  6416. return this.GetRuntimeAssembly(null, null);
  6417. }
  6418. public System.Reflection.Assembly GetRuntimeAssembly(System.Security.Policy.Evidence evidence)
  6419. {
  6420. return this.GetRuntimeAssembly(evidence, null);
  6421. }
  6422. public System.Reflection.Assembly GetRuntimeAssembly(AppDomain targetAppDomain)
  6423. {
  6424. return this.GetRuntimeAssembly(null, targetAppDomain);
  6425. }
  6426. // TODO: Evidence is obsolete but I'm not sure if it can be removed yet as this can parse assemblies from
  6427. // prior framework versions that do use it so we'll just suppress the warning for now.
  6428. #pragma warning disable 0618
  6429. public System.Reflection.Assembly GetRuntimeAssembly(System.Security.Policy.Evidence evidence, AppDomain targetAppDomain)
  6430. {
  6431. System.Reflection.Assembly result = this.cachedRuntimeAssembly == null ? null : this.cachedRuntimeAssembly.Value;
  6432. if(result == null || evidence != null || targetAppDomain != null)
  6433. {
  6434. lock(this)
  6435. {
  6436. if(this.cachedRuntimeAssembly != null && evidence == null && targetAppDomain == null)
  6437. return this.cachedRuntimeAssembly.Value;
  6438. if(targetAppDomain == null)
  6439. targetAppDomain = AppDomain.CurrentDomain;
  6440. if(this.Location != null)
  6441. {
  6442. string name = this.StrongName;
  6443. System.Reflection.Assembly[] alreadyLoadedAssemblies = targetAppDomain.GetAssemblies();
  6444. if(alreadyLoadedAssemblies != null)
  6445. for(int i = 0, n = alreadyLoadedAssemblies.Length; i < n; i++)
  6446. {
  6447. System.Reflection.Assembly a = alreadyLoadedAssemblies[i];
  6448. if(a == null)
  6449. continue;
  6450. if(a.FullName == name)
  6451. {
  6452. result = a;
  6453. break;
  6454. }
  6455. }
  6456. if(result == null)
  6457. {
  6458. if(evidence != null)
  6459. result = targetAppDomain.Load(this.GetAssemblyName(), evidence);
  6460. else
  6461. result = targetAppDomain.Load(this.GetAssemblyName());
  6462. }
  6463. }
  6464. if(result != null && evidence == null && targetAppDomain == AppDomain.CurrentDomain)
  6465. {
  6466. this.AddCachedAssembly(result);
  6467. this.cachedRuntimeAssembly = new CachedRuntimeAssembly(result);
  6468. }
  6469. }
  6470. }
  6471. return result;
  6472. }
  6473. #pragma warning restore 0618
  6474. private void AddCachedAssembly(System.Reflection.Assembly/*!*/ runtimeAssembly)
  6475. {
  6476. if(AssemblyNode.CompiledAssemblies == null)
  6477. AssemblyNode.CompiledAssemblies = Hashtable.Synchronized(new Hashtable());
  6478. AssemblyNode.CompiledAssemblies[runtimeAssembly] = new WeakReference(this);
  6479. }
  6480. private static string GetKeyString(byte[] publicKey)
  6481. {
  6482. if(publicKey == null)
  6483. return null;
  6484. int n = publicKey.Length;
  6485. StringBuilder str;
  6486. if(n > 8)
  6487. {
  6488. System.Security.Cryptography.SHA1 sha1 = new System.Security.Cryptography.SHA1CryptoServiceProvider();
  6489. publicKey = sha1.ComputeHash(publicKey);
  6490. byte[] token = new byte[8];
  6491. for(int i = 0, m = publicKey.Length - 1; i < 8; i++)
  6492. token[i] = publicKey[m - i];
  6493. publicKey = token;
  6494. n = 8;
  6495. }
  6496. if(n == 0)
  6497. str = new StringBuilder(", PublicKeyToken=null");
  6498. else
  6499. str = new StringBuilder(", PublicKeyToken=", n * 2 + 17);
  6500. for(int i = 0; i < n; i++)
  6501. str.Append(publicKey[i].ToString("x2"));
  6502. return str.ToString();
  6503. }
  6504. protected TrivialHashtable friends;
  6505. public virtual bool MayAccessInternalTypesOf(AssemblyNode assembly)
  6506. {
  6507. if(this == assembly)
  6508. return true;
  6509. if(assembly == null || SystemTypes.InternalsVisibleToAttribute == null)
  6510. return false;
  6511. if(this.friends == null)
  6512. this.friends = new TrivialHashtable();
  6513. object ob = this.friends[assembly.UniqueKey];
  6514. if(ob == (object)string.Empty)
  6515. return false;
  6516. if(ob == this)
  6517. return true;
  6518. AttributeList attributes = assembly.Attributes;
  6519. for(int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++)
  6520. {
  6521. //^ assert attributes != null;
  6522. AttributeNode attr = attributes[i];
  6523. if(attr == null)
  6524. continue;
  6525. MemberBinding mb = attr.Constructor as MemberBinding;
  6526. if(mb != null)
  6527. {
  6528. if(mb.BoundMember == null)
  6529. continue;
  6530. if(mb.BoundMember.DeclaringType != SystemTypes.InternalsVisibleToAttribute)
  6531. continue;
  6532. }
  6533. else
  6534. {
  6535. Literal lit = attr.Constructor as Literal;
  6536. if(lit == null)
  6537. continue;
  6538. if((lit.Value as TypeNode) != SystemTypes.InternalsVisibleToAttribute)
  6539. continue;
  6540. }
  6541. if(attr.Expressions == null || attr.Expressions.Count < 1)
  6542. continue;
  6543. Literal argLit = attr.Expressions[0] as Literal;
  6544. if(argLit == null)
  6545. continue;
  6546. string friendName = argLit.Value as string;
  6547. if(friendName == null)
  6548. continue;
  6549. try
  6550. {
  6551. AssemblyReference ar = new AssemblyReference(friendName);
  6552. byte[] tok = ar.PublicKeyToken;
  6553. if(tok != null && this.PublicKeyOrToken != null)
  6554. tok = this.PublicKeyToken;
  6555. if(!ar.Matches(this.Name, ar.Version, ar.Culture, tok))
  6556. continue;
  6557. }
  6558. catch(ArgumentException e)
  6559. {
  6560. if(this.MetadataImportErrors == null)
  6561. this.MetadataImportErrors = new ArrayList();
  6562. this.MetadataImportErrors.Add(e.Message);
  6563. continue;
  6564. }
  6565. this.friends[assembly.UniqueKey] = this;
  6566. return true;
  6567. }
  6568. this.friends[assembly.UniqueKey] = string.Empty;
  6569. return false;
  6570. }
  6571. public AssemblyReferenceList GetFriendAssemblies()
  6572. {
  6573. if(SystemTypes.InternalsVisibleToAttribute == null)
  6574. return null;
  6575. AttributeList attributes = this.Attributes;
  6576. if(attributes == null)
  6577. return null;
  6578. int n = attributes.Count;
  6579. if(n == 0)
  6580. return null;
  6581. AssemblyReferenceList result = new AssemblyReferenceList();
  6582. for(int i = 0; i < n; i++)
  6583. {
  6584. AttributeNode attr = attributes[i];
  6585. if(attr == null)
  6586. continue;
  6587. MemberBinding mb = attr.Constructor as MemberBinding;
  6588. if(mb != null)
  6589. {
  6590. if(mb.BoundMember == null)
  6591. continue;
  6592. if(mb.BoundMember.DeclaringType != SystemTypes.InternalsVisibleToAttribute)
  6593. continue;
  6594. }
  6595. else
  6596. {
  6597. Literal lit = attr.Constructor as Literal;
  6598. if(lit == null)
  6599. continue;
  6600. if((lit.Value as TypeNode) != SystemTypes.InternalsVisibleToAttribute)
  6601. continue;
  6602. }
  6603. if(attr.Expressions == null || attr.Expressions.Count < 1)
  6604. continue;
  6605. Literal argLit = attr.Expressions[0] as Literal;
  6606. if(argLit == null)
  6607. continue;
  6608. string friendName = argLit.Value as string;
  6609. if(friendName == null)
  6610. continue;
  6611. result.Add(new AssemblyReference(friendName));
  6612. }
  6613. return result;
  6614. }
  6615. /// <summary>
  6616. /// The attributes associated with this module. This corresponds to C# custom attributes with the module target specifier.
  6617. /// </summary>
  6618. public virtual AttributeList ModuleAttributes
  6619. {
  6620. get
  6621. {
  6622. if(this.moduleAttributes != null)
  6623. return this.moduleAttributes;
  6624. if(this.provideCustomAttributes != null)
  6625. {
  6626. lock(Module.GlobalLock)
  6627. {
  6628. if(this.moduleAttributes == null)
  6629. this.provideCustomAttributes(this);
  6630. }
  6631. }
  6632. else
  6633. this.moduleAttributes = new AttributeList();
  6634. return this.moduleAttributes;
  6635. }
  6636. set
  6637. {
  6638. this.moduleAttributes = value;
  6639. }
  6640. }
  6641. protected AttributeList moduleAttributes;
  6642. protected byte[] token;
  6643. public virtual byte[] PublicKeyToken
  6644. {
  6645. get
  6646. {
  6647. if(this.token != null)
  6648. return this.token;
  6649. if(this.PublicKeyOrToken == null || this.PublicKeyOrToken.Length == 0)
  6650. return null;
  6651. if(this.PublicKeyOrToken.Length == 8)
  6652. return this.token = this.PublicKeyOrToken;
  6653. System.Security.Cryptography.SHA1 sha1 = new System.Security.Cryptography.SHA1CryptoServiceProvider();
  6654. byte[] hashedKey = sha1.ComputeHash(this.PublicKeyOrToken);
  6655. byte[] token = new byte[8];
  6656. for(int i = 0, n = hashedKey.Length - 1; i < 8; i++)
  6657. token[i] = hashedKey[n - i];
  6658. return this.token = token;
  6659. }
  6660. }
  6661. public override string ToString()
  6662. {
  6663. return this.Name;
  6664. }
  6665. }
  6666. public class AssemblyReference : Node
  6667. {
  6668. private byte[] token;
  6669. internal Reader Reader;
  6670. public AssemblyReference() : base(NodeType.AssemblyReference)
  6671. {
  6672. }
  6673. public AssemblyReference(AssemblyNode/*!*/ assembly)
  6674. : base(NodeType.AssemblyReference)
  6675. {
  6676. this.culture = assembly.Culture;
  6677. this.flags = assembly.Flags & ~AssemblyFlags.PublicKey;
  6678. this.hashValue = assembly.HashValue;
  6679. this.name = assembly.Name;
  6680. this.publicKeyOrToken = assembly.PublicKeyOrToken;
  6681. if(assembly.PublicKeyOrToken != null && assembly.PublicKeyOrToken.Length > 8)
  6682. this.flags |= AssemblyFlags.PublicKey;
  6683. this.location = assembly.Location;
  6684. this.version = assembly.Version;
  6685. this.assembly = assembly;
  6686. }
  6687. public AssemblyReference(string assemblyStrongName, SourceContext sctx)
  6688. : this(assemblyStrongName)
  6689. {
  6690. this.SourceContext = sctx;
  6691. }
  6692. public AssemblyReference(string assemblyStrongName)
  6693. : base(NodeType.AssemblyReference)
  6694. {
  6695. AssemblyFlags flags = AssemblyFlags.None;
  6696. if(assemblyStrongName == null) { Debug.Assert(false); assemblyStrongName = ""; }
  6697. int i = 0, n = assemblyStrongName.Length;
  6698. string name = ParseToken(assemblyStrongName, ref i);
  6699. string version = null;
  6700. string culture = null;
  6701. string token = null;
  6702. while(i < n)
  6703. {
  6704. if(assemblyStrongName[i] != ',')
  6705. throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
  6706. ExceptionStrings.InvalidAssemblyStrongName, assemblyStrongName), "assemblyStrongName");
  6707. i++;
  6708. while(i < n && char.IsWhiteSpace(assemblyStrongName[i]))
  6709. i++;
  6710. switch(assemblyStrongName[i])
  6711. {
  6712. case 'v':
  6713. case 'V':
  6714. version = ParseAssignment(assemblyStrongName, "Version", ref i);
  6715. break;
  6716. case 'c':
  6717. case 'C':
  6718. culture = ParseAssignment(assemblyStrongName, "Culture", ref i);
  6719. break;
  6720. case 'p':
  6721. case 'P':
  6722. if(PlatformHelpers.StringCompareOrdinalIgnoreCase(assemblyStrongName, i, "PublicKeyToken", 0, "PublicKeyToken".Length) == 0)
  6723. token = ParseAssignment(assemblyStrongName, "PublicKeyToken", ref i);
  6724. else
  6725. {
  6726. token = ParseAssignment(assemblyStrongName, "PublicKey", ref i);
  6727. flags |= AssemblyFlags.PublicKey;
  6728. }
  6729. break;
  6730. case 'r':
  6731. case 'R':
  6732. string yesOrNo = ParseAssignment(assemblyStrongName, "Retargetable", ref i);
  6733. if(PlatformHelpers.StringCompareOrdinalIgnoreCase(yesOrNo, "Yes") == 0)
  6734. flags |= AssemblyFlags.Retargetable;
  6735. break;
  6736. }
  6737. while(i < n && assemblyStrongName[i] == ']')
  6738. i++;
  6739. }
  6740. while(i < n && char.IsWhiteSpace(assemblyStrongName[i]))
  6741. i++;
  6742. if(i < n)
  6743. throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
  6744. ExceptionStrings.InvalidAssemblyStrongName, assemblyStrongName), "assemblyStrongName");
  6745. if(PlatformHelpers.StringCompareOrdinalIgnoreCase(culture, "neutral") == 0)
  6746. culture = null;
  6747. if(PlatformHelpers.StringCompareOrdinalIgnoreCase(token, "null") == 0)
  6748. token = null;
  6749. byte[] tok = null;
  6750. if(token != null && (n = token.Length) > 0)
  6751. {
  6752. if(n > 16)
  6753. {
  6754. ArrayList tokArr = new ArrayList();
  6755. if(n % 2 == 1)
  6756. {
  6757. tokArr.Add(byte.Parse(token.Substring(0, 1), System.Globalization.NumberStyles.HexNumber, null));
  6758. n--;
  6759. }
  6760. for(i = 0; i < n; i += 2)
  6761. {
  6762. byte b = 0;
  6763. bool goodByte = byte.TryParse(token.Substring(i, 2), System.Globalization.NumberStyles.HexNumber, null, out b);
  6764. Debug.Assert(goodByte);
  6765. tokArr.Add(b);
  6766. }
  6767. tok = (byte[])tokArr.ToArray(typeof(byte));
  6768. }
  6769. else
  6770. {
  6771. ulong tk = ulong.Parse(token, System.Globalization.NumberStyles.HexNumber, null);
  6772. tok = new byte[8];
  6773. tok[0] = (byte)(tk >> 56);
  6774. tok[1] = (byte)(tk >> 48);
  6775. tok[2] = (byte)(tk >> 40);
  6776. tok[3] = (byte)(tk >> 32);
  6777. tok[4] = (byte)(tk >> 24);
  6778. tok[5] = (byte)(tk >> 16);
  6779. tok[6] = (byte)(tk >> 8);
  6780. tok[7] = (byte)tk;
  6781. }
  6782. }
  6783. this.culture = culture;
  6784. this.name = name;
  6785. this.publicKeyOrToken = tok;
  6786. this.version = version == null || version.Length == 0 ? null : new Version(version);
  6787. this.flags = flags;
  6788. }
  6789. private static string ParseToken(string/*!*/ assemblyStrongName, ref int i)
  6790. {
  6791. Debug.Assert(assemblyStrongName != null);
  6792. int n = assemblyStrongName.Length;
  6793. Debug.Assert(0 <= i && i < n);
  6794. while(i < n && char.IsWhiteSpace(assemblyStrongName[i]))
  6795. i++;
  6796. StringBuilder sb = new StringBuilder(n);
  6797. while(i < n)
  6798. {
  6799. char ch = assemblyStrongName[i];
  6800. if(ch == ',' || ch == ']' || char.IsWhiteSpace(ch))
  6801. break;
  6802. sb.Append(ch);
  6803. i++;
  6804. }
  6805. while(i < n && char.IsWhiteSpace(assemblyStrongName[i]))
  6806. i++;
  6807. return sb.ToString();
  6808. }
  6809. private static string ParseAssignment(string/*!*/ assemblyStrongName, string/*!*/ target, ref int i)
  6810. {
  6811. Debug.Assert(assemblyStrongName != null && target != null);
  6812. int n = assemblyStrongName.Length;
  6813. Debug.Assert(0 < i && i < n);
  6814. if(PlatformHelpers.StringCompareOrdinalIgnoreCase(assemblyStrongName, i, target, 0, target.Length) != 0)
  6815. goto throwError;
  6816. i += target.Length;
  6817. while(i < n && char.IsWhiteSpace(assemblyStrongName[i]))
  6818. i++;
  6819. if(i >= n || assemblyStrongName[i] != '=')
  6820. goto throwError;
  6821. i++;
  6822. if(i >= n)
  6823. goto throwError;
  6824. return ParseToken(assemblyStrongName, ref i);
  6825. throwError:
  6826. throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
  6827. ExceptionStrings.InvalidAssemblyStrongName, assemblyStrongName), "assemblyStrongName");
  6828. }
  6829. private string culture;
  6830. public string Culture
  6831. {
  6832. get { return this.culture; }
  6833. set { this.culture = value; }
  6834. }
  6835. private AssemblyFlags flags;
  6836. public AssemblyFlags Flags
  6837. {
  6838. get { return this.flags; }
  6839. set { this.flags = value; }
  6840. }
  6841. private byte[] hashValue;
  6842. public byte[] HashValue
  6843. {
  6844. get { return this.hashValue; }
  6845. set { this.hashValue = value; }
  6846. }
  6847. private string name;
  6848. public string Name
  6849. {
  6850. get { return this.name; }
  6851. set { this.name = value; }
  6852. }
  6853. private byte[] publicKeyOrToken;
  6854. public byte[] PublicKeyOrToken
  6855. {
  6856. get { return this.publicKeyOrToken; }
  6857. set { this.publicKeyOrToken = value; }
  6858. }
  6859. private System.Version version;
  6860. public System.Version Version
  6861. {
  6862. get { return this.version; }
  6863. set { this.version = value; }
  6864. }
  6865. private string location;
  6866. public string Location
  6867. {
  6868. get { return this.location; }
  6869. set { this.location = value; }
  6870. }
  6871. protected internal AssemblyNode assembly;
  6872. public virtual AssemblyNode Assembly
  6873. {
  6874. get
  6875. {
  6876. if(this.assembly != null)
  6877. return this.assembly;
  6878. if(this.Reader != null)
  6879. return this.assembly = this.Reader.GetAssemblyFromReference(this);
  6880. return null;
  6881. }
  6882. set
  6883. {
  6884. this.assembly = value;
  6885. }
  6886. }
  6887. protected string strongName;
  6888. public virtual string StrongName
  6889. {
  6890. get
  6891. {
  6892. if(this.strongName == null)
  6893. this.strongName = AssemblyNode.GetStrongName(this.Name, this.Version, this.Culture, this.PublicKeyOrToken, (this.Flags & AssemblyFlags.Retargetable) != 0);
  6894. return this.strongName;
  6895. }
  6896. }
  6897. private System.Reflection.AssemblyName assemblyName;
  6898. public System.Reflection.AssemblyName GetAssemblyName()
  6899. {
  6900. if(this.assemblyName == null)
  6901. {
  6902. System.Reflection.AssemblyName aName = new System.Reflection.AssemblyName();
  6903. aName.CultureInfo = new System.Globalization.CultureInfo(this.Culture == null ? "" : this.Culture);
  6904. if(this.PublicKeyOrToken != null && this.PublicKeyOrToken.Length > 8)
  6905. aName.Flags = System.Reflection.AssemblyNameFlags.PublicKey;
  6906. if((this.Flags & AssemblyFlags.Retargetable) != 0)
  6907. aName.Flags |= (System.Reflection.AssemblyNameFlags)AssemblyFlags.Retargetable;
  6908. aName.HashAlgorithm = System.Configuration.Assemblies.AssemblyHashAlgorithm.SHA1;
  6909. if(this.PublicKeyOrToken != null)
  6910. {
  6911. if(this.PublicKeyOrToken.Length > 8)
  6912. aName.SetPublicKey(this.PublicKeyOrToken);
  6913. else if(this.PublicKeyOrToken.Length > 0)
  6914. aName.SetPublicKeyToken(this.PublicKeyOrToken);
  6915. }
  6916. else
  6917. aName.SetPublicKey(new byte[0]);
  6918. aName.Name = this.Name;
  6919. aName.Version = this.Version;
  6920. switch(this.Flags & AssemblyFlags.CompatibilityMask)
  6921. {
  6922. case AssemblyFlags.NonSideBySideCompatible:
  6923. aName.VersionCompatibility = System.Configuration.Assemblies.AssemblyVersionCompatibility.SameDomain;
  6924. break;
  6925. case AssemblyFlags.NonSideBySideProcess:
  6926. aName.VersionCompatibility = System.Configuration.Assemblies.AssemblyVersionCompatibility.SameProcess;
  6927. break;
  6928. case AssemblyFlags.NonSideBySideMachine:
  6929. aName.VersionCompatibility = System.Configuration.Assemblies.AssemblyVersionCompatibility.SameMachine;
  6930. break;
  6931. }
  6932. this.assemblyName = aName;
  6933. }
  6934. return this.assemblyName;
  6935. }
  6936. public bool Matches(string name, Version version, string culture, byte[] publicKeyToken)
  6937. {
  6938. if(culture != null && culture.Length == 0)
  6939. culture = null;
  6940. if(this.Culture != null && this.Culture.Length == 0)
  6941. this.Culture = null;
  6942. if(this.Version != version && this.Version != null && (version == null || !this.Version.Equals(version)))
  6943. return false;
  6944. if(PlatformHelpers.StringCompareOrdinalIgnoreCase(this.Name, name) != 0 ||
  6945. PlatformHelpers.StringCompareOrdinalIgnoreCase(this.Culture, culture) != 0)
  6946. return false;
  6947. if((this.Flags & AssemblyFlags.Retargetable) != 0)
  6948. return true;
  6949. byte[] thisToken = this.PublicKeyToken;
  6950. if(publicKeyToken == null)
  6951. return thisToken == null;
  6952. if(thisToken == publicKeyToken)
  6953. return true;
  6954. if(thisToken == null)
  6955. return false;
  6956. int n = publicKeyToken.Length;
  6957. if(n != thisToken.Length)
  6958. return false;
  6959. for(int i = 0; i < n; i++) if(thisToken[i] != publicKeyToken[i])
  6960. return false;
  6961. return true;
  6962. }
  6963. public bool MatchesIgnoringVersion(AssemblyReference reference)
  6964. {
  6965. if(reference == null)
  6966. return false;
  6967. return this.Matches(reference.Name, this.Version, reference.Culture, reference.PublicKeyToken);
  6968. }
  6969. public byte[] PublicKeyToken
  6970. {
  6971. get
  6972. {
  6973. if(this.token != null)
  6974. return this.token;
  6975. if(this.PublicKeyOrToken == null || this.PublicKeyOrToken.Length == 0)
  6976. return null;
  6977. if(this.PublicKeyOrToken.Length == 8)
  6978. return this.token = this.PublicKeyOrToken;
  6979. System.Security.Cryptography.SHA1 sha = new System.Security.Cryptography.SHA1CryptoServiceProvider();
  6980. byte[] hashedKey = sha.ComputeHash(this.PublicKeyOrToken);
  6981. byte[] token = new byte[8];
  6982. for(int i = 0, n = hashedKey.Length - 1; i < 8; i++)
  6983. token[i] = hashedKey[n - i];
  6984. return this.token = token;
  6985. }
  6986. }
  6987. }
  6988. public class ModuleReference : Node
  6989. {
  6990. private Module module;
  6991. private string name;
  6992. public ModuleReference()
  6993. : base(NodeType.ModuleReference)
  6994. {
  6995. }
  6996. public ModuleReference(string name, Module module)
  6997. : base(NodeType.ModuleReference)
  6998. {
  6999. this.name = name;
  7000. this.module = module;
  7001. }
  7002. public Module Module
  7003. {
  7004. get { return this.module; }
  7005. set { this.module = value; }
  7006. }
  7007. public string Name
  7008. {
  7009. get { return this.name; }
  7010. set { this.name = value; }
  7011. }
  7012. }
  7013. /// <summary>
  7014. /// A member of a Namespace or a TypeNode
  7015. /// </summary>
  7016. public abstract class Member : Node
  7017. {
  7018. /// <summary>The namespace of which this node is a member. Null if this node is a member of type.</summary>
  7019. public Namespace DeclaringNamespace;
  7020. /// <summary>
  7021. /// Indicates that the signature of this member may include unsafe types such as pointers. For methods and properties, it also indicates that the
  7022. /// code may contain unsafe constructions such as pointer arithmetic.
  7023. /// </summary>
  7024. public bool IsUnsafe;
  7025. /// <summary>A list of other nodes that refer to this member. Must be filled in by client code.</summary>
  7026. public NodeList References;
  7027. protected Member(NodeType nodeType)
  7028. : base(nodeType)
  7029. {
  7030. }
  7031. protected Member(TypeNode declaringType, AttributeList attributes, Identifier name, NodeType nodeType)
  7032. : base(nodeType)
  7033. {
  7034. this.attributes = attributes;
  7035. this.declaringType = declaringType;
  7036. this.name = name;
  7037. }
  7038. private TypeNode declaringType;
  7039. /// <summary>The type of which this node is a member. Null if this node is a member of a Namespace.</summary>
  7040. public TypeNode DeclaringType
  7041. {
  7042. get { return this.declaringType; }
  7043. set { this.declaringType = value; }
  7044. }
  7045. private Identifier name;
  7046. /// <summary>The unqualified name of the member.</summary>
  7047. public Identifier Name
  7048. {
  7049. get { return this.name; }
  7050. set { this.name = value; }
  7051. }
  7052. protected AttributeList attributes;
  7053. private bool notObsolete;
  7054. private ObsoleteAttribute obsoleteAttribute;
  7055. /// <summary>
  7056. /// The attributes of this member. Corresponds to custom attribute annotations in C#.
  7057. /// </summary>
  7058. public virtual AttributeList Attributes
  7059. {
  7060. get
  7061. {
  7062. if(this.attributes != null)
  7063. return this.attributes;
  7064. return this.attributes = new AttributeList();
  7065. }
  7066. set
  7067. {
  7068. this.attributes = value;
  7069. }
  7070. }
  7071. protected Member hiddenMember;
  7072. public virtual Member HiddenMember
  7073. {
  7074. get
  7075. {
  7076. return this.hiddenMember;
  7077. }
  7078. set
  7079. {
  7080. this.hiddenMember = value;
  7081. }
  7082. }
  7083. protected bool hidesBaseClassMemberSpecifiedExplicitly;
  7084. protected bool hidesBaseClassMember;
  7085. /// <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>
  7086. public bool HidesBaseClassMember
  7087. {
  7088. get
  7089. {
  7090. if(this.hidesBaseClassMemberSpecifiedExplicitly)
  7091. return this.hidesBaseClassMember;
  7092. else
  7093. return this.HiddenMember != null;
  7094. }
  7095. set
  7096. {
  7097. this.hidesBaseClassMember = value;
  7098. this.hidesBaseClassMemberSpecifiedExplicitly = true;
  7099. }
  7100. }
  7101. protected Member overriddenMember;
  7102. public virtual Member OverriddenMember
  7103. {
  7104. get
  7105. {
  7106. return this.overriddenMember;
  7107. }
  7108. set
  7109. {
  7110. this.overriddenMember = value;
  7111. }
  7112. }
  7113. protected bool overridesBaseClassMemberSpecifiedExplicitly;
  7114. protected bool overridesBaseClassMember;
  7115. /// <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>
  7116. public virtual bool OverridesBaseClassMember
  7117. {
  7118. get
  7119. {
  7120. if(this.overridesBaseClassMemberSpecifiedExplicitly)
  7121. return this.overridesBaseClassMember;
  7122. else
  7123. return this.OverriddenMember != null;
  7124. }
  7125. set
  7126. {
  7127. this.overridesBaseClassMember = value;
  7128. this.overridesBaseClassMemberSpecifiedExplicitly = true;
  7129. }
  7130. }
  7131. /// <summary>
  7132. /// Gets the first attribute of the given type in the attribute list of this member. Returns null if none found.
  7133. /// This should not be called until the AST containing this member has been processed to replace symbolic references
  7134. /// to members with references to the actual members.
  7135. /// </summary>
  7136. public virtual AttributeNode GetAttribute(TypeNode attributeType)
  7137. {
  7138. if(attributeType == null)
  7139. return null;
  7140. AttributeList attributes = this.Attributes;
  7141. for(int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++)
  7142. {
  7143. AttributeNode attr = attributes[i];
  7144. if(attr == null)
  7145. continue;
  7146. MemberBinding mb = attr.Constructor as MemberBinding;
  7147. if(mb != null)
  7148. {
  7149. if(mb.BoundMember == null)
  7150. continue;
  7151. if(mb.BoundMember.DeclaringType != attributeType)
  7152. continue;
  7153. return attr;
  7154. }
  7155. Literal lit = attr.Constructor as Literal;
  7156. if(lit == null)
  7157. continue;
  7158. if((lit.Value as TypeNode) != attributeType)
  7159. continue;
  7160. return attr;
  7161. }
  7162. return null;
  7163. }
  7164. public virtual AttributeList GetFilteredAttributes(TypeNode attributeType)
  7165. {
  7166. if(attributeType == null)
  7167. return this.Attributes;
  7168. AttributeList attributes = this.Attributes;
  7169. AttributeList filtered = new AttributeList();
  7170. for(int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++)
  7171. {
  7172. AttributeNode attr = attributes[i];
  7173. if(attr == null)
  7174. continue;
  7175. MemberBinding mb = attr.Constructor as MemberBinding;
  7176. if(mb != null)
  7177. {
  7178. if(mb.BoundMember != null && mb.BoundMember.DeclaringType == attributeType)
  7179. continue;
  7180. filtered.Add(attr);
  7181. continue;
  7182. }
  7183. Literal lit = attr.Constructor as Literal;
  7184. if(lit != null && (lit.Value as TypeNode) == attributeType)
  7185. continue;
  7186. filtered.Add(attr);
  7187. }
  7188. return filtered;
  7189. }
  7190. /// <summary>
  7191. /// The concatenation of the FullName of the containing member and the name of this member.
  7192. /// Separated with a '.' character if the containing member is a namespace and a '+' character if the containing member is a Type.
  7193. /// Includes the parameter type full names when this member is a method or a property. Also includes (generic) template arguments.
  7194. /// </summary>
  7195. public abstract string/*!*/ FullName { get; }
  7196. /// <summary>True if all references to this member must be from the assembly containing the definition of this member. </summary>
  7197. public abstract bool IsAssembly { get; }
  7198. /// <summary>
  7199. /// True if access to this member is controlled by the compiler and not the runtime. Cannot be accessed from other assemblies since these
  7200. /// are not necessarily controlled by the same compiler.
  7201. /// </summary>
  7202. public abstract bool IsCompilerControlled { get; }
  7203. /// <summary>True if this member can only be accessed from subclasses of the class declaring this member.</summary>
  7204. public abstract bool IsFamily { get; }
  7205. /// <summary>True if this member can only be accessed from subclasses of the class declaring this member, provided that these subclasses are also
  7206. /// contained in the assembly containing this member.</summary>
  7207. public abstract bool IsFamilyAndAssembly { get; }
  7208. /// <summary>True if all references to this member must either be from the assembly containing the definition of this member,
  7209. /// or from a subclass of the class declaring this member.</summary>
  7210. public abstract bool IsFamilyOrAssembly { get; }
  7211. /// <summary>True if all references to this member must be from members of the type declaring this member./// </summary>
  7212. public abstract bool IsPrivate { get; }
  7213. /// <summary>True if the member can be accessed from anywhere./// </summary>
  7214. public abstract bool IsPublic { get; }
  7215. /// <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>
  7216. public abstract bool IsSpecialName { get; }
  7217. /// <summary>True if this member always has the same value or behavior for all instances the declaring type.</summary>
  7218. public abstract bool IsStatic { get; }
  7219. /// <summary>True if another assembly can contain a reference to this member.</summary>
  7220. public abstract bool IsVisibleOutsideAssembly { get; }
  7221. /// <summary>A cached reference to the first Obsolete attribute of this member. Null if no such attribute exists.</summary>
  7222. public ObsoleteAttribute ObsoleteAttribute
  7223. {
  7224. get
  7225. {
  7226. if(this.notObsolete)
  7227. return null;
  7228. if(this.obsoleteAttribute == null)
  7229. {
  7230. AttributeNode attr = this.GetAttribute(SystemTypes.ObsoleteAttribute);
  7231. if(attr != null)
  7232. {
  7233. ExpressionList args = attr.Expressions;
  7234. int numArgs = args == null ? 0 : args.Count;
  7235. Literal lit0 = numArgs > 0 ? args[0] as Literal : null;
  7236. Literal lit1 = numArgs > 1 ? args[1] as Literal : null;
  7237. string message = lit0 != null ? lit0.Value as string : null;
  7238. object isError = lit1 != null ? lit1.Value : null;
  7239. if(isError is bool)
  7240. return this.obsoleteAttribute = new ObsoleteAttribute(message, (bool)isError);
  7241. else
  7242. return this.obsoleteAttribute = new ObsoleteAttribute(message);
  7243. }
  7244. this.notObsolete = true;
  7245. }
  7246. return this.obsoleteAttribute;
  7247. }
  7248. set
  7249. {
  7250. this.obsoleteAttribute = value;
  7251. this.notObsolete = false;
  7252. }
  7253. }
  7254. /// <summary>The source code, if any, corresponding to the value in Documentation.</summary>
  7255. public Node DocumentationNode;
  7256. protected XmlNode documentation;
  7257. /// <summary>The body of an XML element containing a description of this member. Used to associated documentation (such as this comment) with members.
  7258. /// The fragment usually conforms to the structure defined in the C# standard.</summary>
  7259. public virtual XmlNode Documentation
  7260. {
  7261. get
  7262. {
  7263. XmlNode documentation = this.documentation;
  7264. if(documentation != null)
  7265. return documentation;
  7266. TypeNode t = this.DeclaringType;
  7267. if(t == null)
  7268. t = this as TypeNode;
  7269. Module m = t == null ? null : t.DeclaringModule;
  7270. TrivialHashtable cache = m == null ? null : m.GetMemberDocumentationCache();
  7271. if(cache == null)
  7272. return null;
  7273. return this.documentation = (XmlNode)cache[this.DocumentationId.UniqueIdKey];
  7274. }
  7275. set
  7276. {
  7277. this.documentation = value;
  7278. }
  7279. }
  7280. protected Identifier documentationId;
  7281. protected virtual Identifier GetDocumentationId()
  7282. {
  7283. return Identifier.Empty;
  7284. }
  7285. /// <summary>
  7286. /// The value of the name attribute of the XML element whose body is the XML fragment returned by Documentation.
  7287. /// </summary>
  7288. public Identifier DocumentationId
  7289. {
  7290. get
  7291. {
  7292. Identifier documentationId = this.documentationId;
  7293. if(documentationId != null)
  7294. return documentationId;
  7295. return this.DocumentationId = this.GetDocumentationId();
  7296. }
  7297. set
  7298. {
  7299. this.documentationId = value;
  7300. }
  7301. }
  7302. protected string helpText;
  7303. /// <summary>
  7304. /// The value of the summary child element of the XML fragment returned by Documentation. All markup is stripped from the value.
  7305. /// </summary>
  7306. public virtual string HelpText
  7307. {
  7308. get
  7309. {
  7310. string helpText = this.helpText;
  7311. if(helpText != null)
  7312. return helpText;
  7313. XmlNode documentation = this.Documentation;
  7314. if(documentation != null && documentation.HasChildNodes)
  7315. {
  7316. //^ assume documentation.ChildNodes != null;
  7317. foreach(XmlNode child in documentation.ChildNodes)
  7318. if(child.Name == "summary")
  7319. return this.helpText = this.GetHelpText(child);
  7320. }
  7321. return this.helpText = "";
  7322. }
  7323. set
  7324. {
  7325. this.helpText = value;
  7326. }
  7327. }
  7328. public virtual string GetParameterHelpText(string parameterName)
  7329. {
  7330. XmlNode documentation = this.Documentation;
  7331. if(documentation == null || documentation.ChildNodes == null)
  7332. return null;
  7333. foreach(XmlNode cdoc in documentation.ChildNodes)
  7334. {
  7335. if(cdoc == null)
  7336. continue;
  7337. if(cdoc.Name != "param")
  7338. continue;
  7339. if(cdoc.Attributes == null)
  7340. continue;
  7341. foreach(XmlAttribute attr in cdoc.Attributes)
  7342. {
  7343. if(attr == null || attr.Name != "name" || attr.Value != parameterName)
  7344. continue;
  7345. if(!cdoc.HasChildNodes)
  7346. continue;
  7347. return this.GetHelpText(cdoc);
  7348. }
  7349. }
  7350. return null;
  7351. }
  7352. private string GetHelpText(XmlNode node)
  7353. {
  7354. if(node == null)
  7355. return "";
  7356. StringBuilder sb = new StringBuilder();
  7357. if(node.HasChildNodes)
  7358. {
  7359. foreach(XmlNode child in node.ChildNodes)
  7360. {
  7361. switch(child.NodeType)
  7362. {
  7363. case XmlNodeType.Element:
  7364. string str = this.GetHelpText(child);
  7365. if(str == null || str.Length == 0)
  7366. continue;
  7367. if(sb.Length > 0 && !Char.IsPunctuation(str[0]))
  7368. sb.Append(' ');
  7369. sb.Append(str);
  7370. break;
  7371. case XmlNodeType.CDATA:
  7372. case XmlNodeType.Entity:
  7373. case XmlNodeType.Text:
  7374. this.AppendValue(sb, child);
  7375. break;
  7376. }
  7377. }
  7378. }
  7379. else if(node.Attributes != null)
  7380. {
  7381. foreach(XmlAttribute attr in node.Attributes)
  7382. {
  7383. this.AppendValue(sb, attr);
  7384. }
  7385. }
  7386. return sb.ToString();
  7387. }
  7388. private int filterPriority;
  7389. public virtual System.ComponentModel.EditorBrowsableState FilterPriority
  7390. {
  7391. get
  7392. {
  7393. if(this.filterPriority > 0)
  7394. return (System.ComponentModel.EditorBrowsableState)(this.filterPriority - 1);
  7395. int prio = 0;
  7396. XmlNode documentation = this.Documentation;
  7397. if(documentation != null && documentation.HasChildNodes)
  7398. {
  7399. foreach(XmlNode child in documentation.ChildNodes)
  7400. if(child.Name == "filterpriority")
  7401. {
  7402. PlatformHelpers.TryParseInt32(child.InnerText, out prio);
  7403. switch(prio)
  7404. {
  7405. case 2:
  7406. this.filterPriority = (int)System.ComponentModel.EditorBrowsableState.Advanced;
  7407. break;
  7408. case 3:
  7409. this.filterPriority = (int)System.ComponentModel.EditorBrowsableState.Never;
  7410. break;
  7411. default:
  7412. this.filterPriority = (int)System.ComponentModel.EditorBrowsableState.Always;
  7413. break;
  7414. }
  7415. this.filterPriority++;
  7416. return (System.ComponentModel.EditorBrowsableState)(this.filterPriority - 1);
  7417. }
  7418. }
  7419. AttributeList attributes = this.Attributes;
  7420. for(int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++)
  7421. {
  7422. //^ assert attributes != null;
  7423. AttributeNode attr = attributes[i];
  7424. if(attr == null || attr.Type == null)
  7425. continue;
  7426. if(attr.Expressions == null || attr.Expressions.Count < 1)
  7427. continue;
  7428. if(attr.Type.FullName != "System.ComponentModel.EditorBrowsableAttribute")
  7429. continue;
  7430. Literal lit = attr.Expressions[0] as Literal;
  7431. if(lit == null || !(lit.Value is int))
  7432. continue;
  7433. //^ assert lit.Value != null;
  7434. prio = (int)lit.Value;
  7435. return (System.ComponentModel.EditorBrowsableState)((this.filterPriority = prio + 1) - 1);
  7436. }
  7437. return (System.ComponentModel.EditorBrowsableState)((this.filterPriority = 1) - 1);
  7438. }
  7439. set
  7440. {
  7441. this.filterPriority = ((int)value) + 1;
  7442. }
  7443. }
  7444. /// <summary>
  7445. /// Writes out an element with tag "element", name attribute DocumentationId.ToString() and body Documentation using the provided XmlTextWriter instance.
  7446. /// </summary>
  7447. public virtual void WriteDocumentation(XmlTextWriter xwriter)
  7448. {
  7449. if(this.documentation == null || xwriter == null)
  7450. return;
  7451. xwriter.WriteStartElement("member");
  7452. if(this.DocumentationId == null)
  7453. return;
  7454. xwriter.WriteAttributeString("name", this.DocumentationId.ToString());
  7455. this.documentation.WriteContentTo(xwriter);
  7456. xwriter.WriteEndElement();
  7457. }
  7458. private readonly static char[]/*!*/ tags = { 'E', 'F', 'M', 'P', 'T' };
  7459. private void AppendValue(StringBuilder/*!*/ sb, XmlNode/*!*/ node)
  7460. {
  7461. string str = node.Value;
  7462. if(str != null)
  7463. {
  7464. str = str.Trim();
  7465. if(str.Length > 2 && str[1] == ':' && str.LastIndexOfAny(tags, 0, 1) == 0)
  7466. {
  7467. char tag = str[0];
  7468. str = str.Substring(2);
  7469. if(tag == 'T' && str.IndexOf(TargetPlatform.GenericTypeNamesMangleChar) >= 0)
  7470. {
  7471. Module mod = null;
  7472. if(this.DeclaringType != null)
  7473. mod = this.DeclaringType.DeclaringModule;
  7474. else if(this is TypeNode)
  7475. mod = ((TypeNode)this).DeclaringModule;
  7476. if(mod != null)
  7477. {
  7478. Identifier ns;
  7479. Identifier tn;
  7480. int i = str.LastIndexOf('.');
  7481. if(i < 0 || i >= str.Length)
  7482. {
  7483. ns = Identifier.Empty;
  7484. tn = Identifier.For(str);
  7485. }
  7486. else
  7487. {
  7488. ns = Identifier.For(str.Substring(0, i));
  7489. tn = Identifier.For(str.Substring(i + 1));
  7490. }
  7491. TypeNode t = mod.GetType(ns, tn, true);
  7492. if(t != null)
  7493. str = t.GetFullUnmangledNameWithTypeParameters();
  7494. }
  7495. }
  7496. }
  7497. if(str == null || str.Length == 0)
  7498. return;
  7499. bool lastCharWasSpace = false;
  7500. if(sb.Length > 0 && !Char.IsPunctuation(str[0]) && !Char.IsWhiteSpace(str[0]))
  7501. {
  7502. sb.Append(' ');
  7503. lastCharWasSpace = true;
  7504. }
  7505. foreach(char ch in str)
  7506. {
  7507. if(Char.IsWhiteSpace(ch))
  7508. {
  7509. if(lastCharWasSpace)
  7510. continue;
  7511. lastCharWasSpace = true;
  7512. sb.Append(' ');
  7513. }
  7514. else
  7515. {
  7516. lastCharWasSpace = false;
  7517. sb.Append(ch);
  7518. }
  7519. }
  7520. if(sb.Length > 0 && Char.IsWhiteSpace(sb[sb.Length - 1]))
  7521. sb.Length -= 1;
  7522. }
  7523. }
  7524. }
  7525. public class TypeMemberSnippet : Member
  7526. {
  7527. public IParserFactory ParserFactory;
  7528. public TypeMemberSnippet()
  7529. : base(NodeType.TypeMemberSnippet)
  7530. {
  7531. }
  7532. public TypeMemberSnippet(IParserFactory parserFactory, SourceContext sctx)
  7533. : base(NodeType.TypeMemberSnippet)
  7534. {
  7535. this.ParserFactory = parserFactory;
  7536. this.SourceContext = sctx;
  7537. }
  7538. public override string/*!*/ FullName
  7539. {
  7540. get { throw new InvalidOperationException(); }
  7541. }
  7542. public override bool IsCompilerControlled
  7543. {
  7544. get { throw new InvalidOperationException(); }
  7545. }
  7546. public override bool IsAssembly
  7547. {
  7548. get { throw new InvalidOperationException(); }
  7549. }
  7550. public override bool IsFamily
  7551. {
  7552. get { throw new InvalidOperationException(); }
  7553. }
  7554. public override bool IsFamilyAndAssembly
  7555. {
  7556. get { throw new InvalidOperationException(); }
  7557. }
  7558. public override bool IsFamilyOrAssembly
  7559. {
  7560. get { throw new InvalidOperationException(); }
  7561. }
  7562. public override bool IsPrivate
  7563. {
  7564. get { throw new InvalidOperationException(); }
  7565. }
  7566. public override bool IsPublic
  7567. {
  7568. get { throw new InvalidOperationException(); }
  7569. }
  7570. public override bool IsSpecialName
  7571. {
  7572. get { throw new InvalidOperationException(); }
  7573. }
  7574. public override bool IsStatic
  7575. {
  7576. get { throw new InvalidOperationException(); }
  7577. }
  7578. public override bool IsVisibleOutsideAssembly
  7579. {
  7580. get { throw new InvalidOperationException(); }
  7581. }
  7582. }
  7583. /// <summary>
  7584. /// The common base class for all types. This type should not be extended directly.
  7585. /// Instead extend one of the standard subclasses such as Class, Struct or Interface, since in
  7586. /// the CLR a type has to be an instance of one the subclasses, and a type which does not extend
  7587. /// one of these types will have no equivalent in the CLR.
  7588. /// </summary>
  7589. public abstract class TypeNode : Member
  7590. {
  7591. private int classSize;
  7592. /// <summary>Specifies the total size in bytes of instances of types with prescribed layout.</summary>
  7593. public int ClassSize
  7594. {
  7595. get { return this.classSize; }
  7596. set { this.classSize = value; }
  7597. }
  7598. private Module declaringModule;
  7599. /// <summary>The module or assembly to which the compiled type belongs.</summary>
  7600. public Module DeclaringModule
  7601. {
  7602. get { return this.declaringModule; }
  7603. set { this.declaringModule = value; }
  7604. }
  7605. private TypeFlags flags;
  7606. public TypeFlags Flags
  7607. {
  7608. get { return this.flags; }
  7609. set { this.flags = value; }
  7610. }
  7611. /// <summary>The interfaces implemented by this class or struct, or the extended by this interface.</summary>
  7612. public virtual InterfaceList Interfaces
  7613. {
  7614. get { return this.interfaces == null ? new InterfaceList() : this.interfaces; }
  7615. set { this.interfaces = value; }
  7616. }
  7617. protected InterfaceList interfaces;
  7618. public InterfaceList InterfaceExpressions;
  7619. private Identifier @namespace;
  7620. /// <summary>The namespace to which this type belongs. Null if the type is nested inside another type.</summary>
  7621. public Identifier Namespace
  7622. {
  7623. get { return this.@namespace; }
  7624. set { this.@namespace = value; }
  7625. }
  7626. private int packingSize;
  7627. /// <summary>Specifies the alignment of fields within types with prescribed layout.</summary>
  7628. public int PackingSize
  7629. {
  7630. get { return this.packingSize; }
  7631. set { this.packingSize = value; }
  7632. }
  7633. /// <summary>If this type is the combined result of a number of partial type definitions, this lists the partial definitions.</summary>
  7634. public TypeNodeList IsDefinedBy;
  7635. /// <summary>
  7636. /// True if this type is the result of a template instantiation with arguments that are themselves template parameters.
  7637. /// Used to model template instantiations occurring inside templates.
  7638. /// </summary>
  7639. public bool IsNotFullySpecialized;
  7640. public bool NewTemplateInstanceIsRecursive;
  7641. /// <summary>
  7642. /// If this type is a partial definition, the value of this is the combined type resulting from all the partial definitions.
  7643. /// </summary>
  7644. public TypeNode PartiallyDefines;
  7645. /// <summary>
  7646. /// The list of extensions of this type, if it's a non-extension type.
  7647. /// all extensions implement the IExtendTypeNode interface (in the Sing# code base).
  7648. /// null = empty list
  7649. /// </summary>
  7650. private TypeNodeList extensions = null;
  7651. /// <summary>
  7652. /// Whether or not the list of extensions has been examined;
  7653. /// it's a bug to record a new extension after extensions have been examined.
  7654. /// </summary>
  7655. private bool extensionsExamined = false;
  7656. /// <summary>
  7657. /// Record another extension of this type.
  7658. /// </summary>
  7659. /// <param name="extension"></param>
  7660. public void RecordExtension(TypeNode extension)
  7661. {
  7662. Debug.Assert(!extensionsExamined, "adding an extension after they've already been examined");
  7663. if(this.extensions == null)
  7664. this.extensions = new TypeNodeList();
  7665. this.extensions.Add(extension);
  7666. }
  7667. /// <summary>
  7668. /// The property that should be accessed by clients to get the list of extensions of this type.
  7669. /// </summary>
  7670. public TypeNodeList Extensions
  7671. {
  7672. get
  7673. {
  7674. this.extensionsExamined = true;
  7675. return this.extensions;
  7676. }
  7677. set
  7678. {
  7679. Debug.Assert(!extensionsExamined, "setting extensions after they've already been examined");
  7680. this.extensions = value;
  7681. }
  7682. }
  7683. /// <summary>
  7684. /// When duplicating a type node, we want to transfer the extensions and the extensionsExamined flag without
  7685. /// treating this as a "touch" that sets the examined flag. Pretty ugly, though.
  7686. /// </summary>
  7687. public TypeNodeList ExtensionsNoTouch
  7688. {
  7689. get { return this.extensions; }
  7690. }
  7691. /// <summary>
  7692. /// Copy a (possibly transformed) set of extensions from source to the
  7693. /// receiver, including whether or not the extensions have been examined.
  7694. /// </summary>
  7695. public void DuplicateExtensions(TypeNode source, TypeNodeList newExtensions)
  7696. {
  7697. if(source == null)
  7698. return;
  7699. this.extensions = newExtensions;
  7700. this.extensionsExamined = source.extensionsExamined;
  7701. }
  7702. /// <summary>
  7703. /// If the receiver is a type extension, return the extendee, otherwise return the receiver.
  7704. /// [The identity function, except for dialects (e.g. Extensible Sing#) that allow
  7705. /// extensions and differing views of types]
  7706. /// </summary>
  7707. public virtual TypeNode/*!*/ EffectiveTypeNode
  7708. {
  7709. get
  7710. {
  7711. return this;
  7712. }
  7713. }
  7714. /// <summary>
  7715. /// Return whether t1 represents the same type as t2 (or both are null).
  7716. /// This copes with the cases where t1 and/or t2 may be type views and/or type extensions, as
  7717. /// in Extensible Sing#.
  7718. /// </summary>
  7719. public static bool operator ==(TypeNode t1, TypeNode t2)
  7720. {
  7721. return
  7722. (object)t1 == null ?
  7723. (object)t2 == null :
  7724. (object)t2 != null && (object)t1.EffectiveTypeNode == (object)t2.EffectiveTypeNode;
  7725. }
  7726. // modify the other operations related to equality
  7727. public static bool operator !=(TypeNode t1, TypeNode t2)
  7728. {
  7729. return !(t1 == t2);
  7730. }
  7731. public override bool Equals(Object other)
  7732. {
  7733. return this == (other as TypeNode);
  7734. }
  7735. public override int GetHashCode()
  7736. {
  7737. TypeNode tn = this.EffectiveTypeNode;
  7738. if((object)tn == (object)this)
  7739. {
  7740. return base.GetHashCode();
  7741. }
  7742. else
  7743. {
  7744. return tn.GetHashCode();
  7745. }
  7746. }
  7747. /// <summary>
  7748. /// A delegate that is called the first time Members is accessed, if non-null.
  7749. /// Provides for incremental construction of the type node.
  7750. /// Must not leave Members null.
  7751. /// </summary>
  7752. public TypeMemberProvider ProvideTypeMembers;
  7753. /// <summary>
  7754. /// The type of delegates that fill in the Members property of the given type.
  7755. /// </summary>
  7756. public delegate void TypeMemberProvider(TypeNode/*!*/ type, object/*!*/ handle);
  7757. /// <summary>
  7758. /// A delegate that is called the first time NestedTypes is accessed, if non-null.
  7759. /// </summary>
  7760. public NestedTypeProvider ProvideNestedTypes;
  7761. /// <summary>
  7762. /// The type of delegates that fill in the NestedTypes property of the given type.
  7763. /// </summary>
  7764. public delegate void NestedTypeProvider(TypeNode/*!*/ type, object/*!*/ handle);
  7765. /// <summary>
  7766. /// A delegate that is called the first time Attributes is accessed, if non-null.
  7767. /// Provides for incremental construction of the type node.
  7768. /// Must not leave Attributes null.
  7769. /// </summary>
  7770. public TypeAttributeProvider ProvideTypeAttributes;
  7771. /// <summary>
  7772. /// The type of delegates that fill in the Attributes property of the given type.
  7773. /// </summary>
  7774. public delegate void TypeAttributeProvider(TypeNode/*!*/ type, object/*!*/ handle);
  7775. /// <summary>
  7776. /// Opaque information passed as a parameter to the delegates in ProvideTypeMembers et al.
  7777. /// Typically used to associate this namespace instance with a helper object.
  7778. /// </summary>
  7779. public object ProviderHandle;
  7780. private TypeNodeList templateInstances;
  7781. /// <summary>Contains all the types instantiated from this non generic template type.</summary>
  7782. public TypeNodeList TemplateInstances
  7783. {
  7784. get { return this.templateInstances; }
  7785. set { this.templateInstances = value; }
  7786. }
  7787. internal TypeNode(NodeType nodeType)
  7788. : base(nodeType)
  7789. {
  7790. }
  7791. internal TypeNode(NodeType nodeType, NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  7792. : base(nodeType)
  7793. {
  7794. this.ProvideNestedTypes = provideNestedTypes;
  7795. this.ProvideTypeAttributes = provideAttributes;
  7796. this.ProvideTypeMembers = provideMembers;
  7797. this.ProviderHandle = handle;
  7798. this.isNormalized = true;
  7799. }
  7800. internal TypeNode(Module declaringModule, TypeNode declaringType, AttributeList attributes, TypeFlags flags,
  7801. Identifier Namespace, Identifier name, InterfaceList interfaces, MemberList members, NodeType nodeType)
  7802. : base(null, attributes, name, nodeType)
  7803. {
  7804. this.DeclaringModule = declaringModule;
  7805. this.DeclaringType = declaringType;
  7806. this.Flags = flags;
  7807. this.Interfaces = interfaces;
  7808. this.members = members;
  7809. this.Namespace = Namespace;
  7810. }
  7811. public override AttributeList Attributes
  7812. {
  7813. get
  7814. {
  7815. if(this.attributes == null)
  7816. {
  7817. if(this.ProvideTypeAttributes != null && this.ProviderHandle != null)
  7818. {
  7819. lock(Module.GlobalLock)
  7820. {
  7821. if(this.attributes == null)
  7822. {
  7823. // !EFW - Assign an empty list first. If not, it can get stuck in an
  7824. // endless loop if a type has an attribute with a type parameter that
  7825. // references the type being parsed. For example:
  7826. //
  7827. // [SomeAttribute(typeof(SomeClass<object>))]
  7828. // public class SomeClass<T> { }
  7829. //
  7830. this.attributes = new AttributeList();
  7831. this.ProvideTypeAttributes(this, this.ProviderHandle);
  7832. }
  7833. }
  7834. }
  7835. else
  7836. this.attributes = new AttributeList();
  7837. }
  7838. return this.attributes;
  7839. }
  7840. set
  7841. {
  7842. this.attributes = value;
  7843. }
  7844. }
  7845. protected SecurityAttributeList securityAttributes;
  7846. /// <summary>Contains declarative security information associated with the type.</summary>
  7847. public SecurityAttributeList SecurityAttributes
  7848. {
  7849. get
  7850. {
  7851. if(this.securityAttributes != null)
  7852. return this.securityAttributes;
  7853. if(this.attributes == null)
  7854. {
  7855. // Getting the type attributes also gets the security attributes in the case of a type that
  7856. // was read in by the Reader
  7857. AttributeList al = this.Attributes;
  7858. if(al != null)
  7859. al = null;
  7860. if(this.securityAttributes != null)
  7861. return this.securityAttributes;
  7862. }
  7863. return this.securityAttributes = new SecurityAttributeList();
  7864. }
  7865. set
  7866. {
  7867. this.securityAttributes = value;
  7868. }
  7869. }
  7870. /// <summary>The type from which this type is derived. Null in the case of interfaces and System.Object.</summary>
  7871. public virtual TypeNode BaseType
  7872. {
  7873. get
  7874. {
  7875. switch(this.NodeType)
  7876. {
  7877. case NodeType.ArrayType:
  7878. return CoreSystemTypes.Array;
  7879. case NodeType.ClassParameter:
  7880. case NodeType.Class:
  7881. return ((Class)this).BaseClass;
  7882. case NodeType.DelegateNode:
  7883. return CoreSystemTypes.MulticastDelegate;
  7884. case NodeType.EnumNode:
  7885. return CoreSystemTypes.Enum;
  7886. case NodeType.Struct:
  7887. case NodeType.TupleType:
  7888. case NodeType.TypeAlias:
  7889. case NodeType.TypeIntersection:
  7890. case NodeType.TypeUnion:
  7891. return CoreSystemTypes.ValueType;
  7892. default:
  7893. return null;
  7894. }
  7895. }
  7896. }
  7897. protected internal MemberList defaultMembers;
  7898. /// <summary>A list of any members of this type that have the DefaultMember attribute.</summary>
  7899. public virtual MemberList DefaultMembers
  7900. {
  7901. get
  7902. {
  7903. int n = this.Members.Count;
  7904. if(n != this.memberCount)
  7905. {
  7906. this.UpdateMemberTable(n);
  7907. this.defaultMembers = null;
  7908. }
  7909. if(this.defaultMembers == null)
  7910. {
  7911. AttributeList attrs = this.Attributes;
  7912. Identifier defMemName = null;
  7913. for(int j = 0, m = attrs == null ? 0 : attrs.Count; j < m; j++)
  7914. {
  7915. //^ assert attrs != null;
  7916. AttributeNode attr = attrs[j];
  7917. if(attr == null)
  7918. continue;
  7919. MemberBinding mb = attr.Constructor as MemberBinding;
  7920. if(mb != null && mb.BoundMember != null && mb.BoundMember.DeclaringType == SystemTypes.DefaultMemberAttribute)
  7921. {
  7922. if(attr.Expressions != null && attr.Expressions.Count > 0)
  7923. {
  7924. Literal lit = attr.Expressions[0] as Literal;
  7925. if(lit != null && lit.Value is string)
  7926. defMemName = Identifier.For((string)lit.Value);
  7927. }
  7928. break;
  7929. }
  7930. Literal litc = attr.Constructor as Literal;
  7931. if(litc != null && (litc.Value as TypeNode) == SystemTypes.DefaultMemberAttribute)
  7932. {
  7933. if(attr.Expressions != null && attr.Expressions.Count > 0)
  7934. {
  7935. Literal lit = attr.Expressions[0] as Literal;
  7936. if(lit != null && lit.Value is string)
  7937. defMemName = Identifier.For((string)lit.Value);
  7938. }
  7939. break;
  7940. }
  7941. }
  7942. if(defMemName != null)
  7943. this.defaultMembers = this.GetMembersNamed(defMemName);
  7944. else
  7945. this.defaultMembers = new MemberList();
  7946. }
  7947. return this.defaultMembers;
  7948. }
  7949. set
  7950. {
  7951. this.defaultMembers = value;
  7952. }
  7953. }
  7954. protected string fullName;
  7955. public override string/*!*/ FullName
  7956. {
  7957. get
  7958. {
  7959. if(this.fullName != null)
  7960. return this.fullName;
  7961. if(this.DeclaringType != null)
  7962. return this.fullName = this.DeclaringType.FullName + "+" + (this.Name == null ? "" : this.Name.ToString());
  7963. else if(this.Namespace != null && this.Namespace.UniqueIdKey != Identifier.Empty.UniqueIdKey)
  7964. return this.fullName = this.Namespace.ToString() + "." + (this.Name == null ? "" : this.Name.ToString());
  7965. else if(this.Name != null)
  7966. return this.fullName = this.Name.ToString();
  7967. else
  7968. return this.fullName = "";
  7969. }
  7970. }
  7971. // the same as FullName, except for dialects like Sing# with type extensions where names of
  7972. // type extensions may get mangled; in that case, this reports the name of the effective type node.
  7973. public virtual string FullNameDuringParsing
  7974. {
  7975. get { return this.FullName; }
  7976. }
  7977. public virtual string GetFullUnmangledNameWithoutTypeParameters()
  7978. {
  7979. if(this.DeclaringType != null)
  7980. return this.DeclaringType.GetFullUnmangledNameWithoutTypeParameters() + "+" + this.GetUnmangledNameWithoutTypeParameters();
  7981. else if(this.Namespace != null && this.Namespace.UniqueIdKey != Identifier.Empty.UniqueIdKey)
  7982. return this.Namespace.ToString() + "." + this.GetUnmangledNameWithoutTypeParameters();
  7983. else
  7984. return this.GetUnmangledNameWithoutTypeParameters();
  7985. }
  7986. public virtual string GetFullUnmangledNameWithTypeParameters()
  7987. {
  7988. if(this.DeclaringType != null)
  7989. return this.DeclaringType.GetFullUnmangledNameWithTypeParameters() + "+" + this.GetUnmangledNameWithTypeParameters(true);
  7990. else if(this.Namespace != null && this.Namespace.UniqueIdKey != Identifier.Empty.UniqueIdKey)
  7991. return this.Namespace.ToString() + "." + this.GetUnmangledNameWithTypeParameters(true);
  7992. else
  7993. return this.GetUnmangledNameWithTypeParameters(true);
  7994. }
  7995. public virtual string GetUnmangledNameWithTypeParameters()
  7996. {
  7997. return this.GetUnmangledNameWithTypeParameters(false);
  7998. }
  7999. private string GetUnmangledNameWithTypeParameters(bool fullNamesForTypeParameters)
  8000. {
  8001. StringBuilder sb = new StringBuilder(this.GetUnmangledNameWithoutTypeParameters());
  8002. TypeNodeList templateParameters = this.TemplateParameters;
  8003. if(this.Template != null)
  8004. templateParameters = this.TemplateArguments;
  8005. for(int i = 0, n = templateParameters == null ? 0 : templateParameters.Count; i < n; i++)
  8006. {
  8007. //^ assert templateParameters != null;
  8008. TypeNode tpar = templateParameters[i];
  8009. if(tpar == null)
  8010. continue;
  8011. if(i == 0)
  8012. sb.Append('<');
  8013. else
  8014. sb.Append(',');
  8015. if(tpar.Name != null)
  8016. if(fullNamesForTypeParameters)
  8017. sb.Append(tpar.GetFullUnmangledNameWithTypeParameters());
  8018. else
  8019. sb.Append(tpar.GetUnmangledNameWithTypeParameters());
  8020. if(i == n - 1)
  8021. sb.Append('>');
  8022. }
  8023. return sb.ToString();
  8024. }
  8025. public virtual string/*!*/ GetUnmangledNameWithoutTypeParameters()
  8026. {
  8027. char[] mangleChars = new[] { TargetPlatform.GenericTypeNamesMangleChar, '>' };
  8028. if(this.Template != null)
  8029. return this.Template.GetUnmangledNameWithoutTypeParameters();
  8030. if(this.Name == null)
  8031. return "";
  8032. string name = this.Name.ToString();
  8033. if(this.TemplateParameters != null && this.TemplateParameters.Count > 0)
  8034. {
  8035. int lastMangle = name.LastIndexOfAny(mangleChars);
  8036. if(lastMangle >= 0)
  8037. {
  8038. if(name[lastMangle] == '>')
  8039. lastMangle++;
  8040. return name.Substring(0, lastMangle);
  8041. }
  8042. }
  8043. return name;
  8044. }
  8045. public virtual string GetSerializedTypeName()
  8046. {
  8047. bool isAssemblyQualified = true;
  8048. return this.GetSerializedTypeName(this, ref isAssemblyQualified);
  8049. }
  8050. string GetSerializedTypeName(TypeNode/*!*/ type, ref bool isAssemblyQualified)
  8051. {
  8052. if(type == null)
  8053. return null;
  8054. StringBuilder sb = new StringBuilder();
  8055. TypeModifier tMod = type as TypeModifier;
  8056. if(tMod != null)
  8057. type = tMod.ModifiedType;
  8058. ArrayType arrType = type as ArrayType;
  8059. if(arrType != null)
  8060. {
  8061. type = arrType.ElementType;
  8062. bool isAssemQual = false;
  8063. this.AppendSerializedTypeName(sb, arrType.ElementType, ref isAssemQual);
  8064. if(arrType.IsSzArray())
  8065. sb.Append("[]");
  8066. else
  8067. {
  8068. sb.Append('[');
  8069. if(arrType.Rank == 1)
  8070. sb.Append('*');
  8071. for(int i = 1; i < arrType.Rank; i++)
  8072. sb.Append(',');
  8073. sb.Append(']');
  8074. }
  8075. goto done;
  8076. }
  8077. Pointer pointer = type as Pointer;
  8078. if(pointer != null)
  8079. {
  8080. type = pointer.ElementType;
  8081. bool isAssemQual = false;
  8082. this.AppendSerializedTypeName(sb, pointer.ElementType, ref isAssemQual);
  8083. sb.Append('*');
  8084. goto done;
  8085. }
  8086. Reference reference = type as Reference;
  8087. if(reference != null)
  8088. {
  8089. type = reference.ElementType;
  8090. bool isAssemQual = false;
  8091. this.AppendSerializedTypeName(sb, reference.ElementType, ref isAssemQual);
  8092. sb.Append('&');
  8093. goto done;
  8094. }
  8095. if(type.Template == null)
  8096. sb.Append(type.FullName);
  8097. else
  8098. {
  8099. sb.Append(type.Template.FullName);
  8100. sb.Append('[');
  8101. for(int i = 0, n = type.TemplateArguments == null ? 0 : type.TemplateArguments.Count; i < n; i++)
  8102. {
  8103. //^ assert type.TemplateArguments != null;
  8104. bool isAssemQual = true;
  8105. this.AppendSerializedTypeName(sb, type.TemplateArguments[i], ref isAssemQual);
  8106. if(i < n - 1)
  8107. sb.Append(',');
  8108. }
  8109. sb.Append(']');
  8110. }
  8111. done:
  8112. if(isAssemblyQualified)
  8113. this.AppendAssemblyQualifierIfNecessary(sb, type, out isAssemblyQualified);
  8114. return sb.ToString();
  8115. }
  8116. void AppendAssemblyQualifierIfNecessary(StringBuilder/*!*/ sb, TypeNode type, out bool isAssemQualified)
  8117. {
  8118. isAssemQualified = false;
  8119. if(type == null)
  8120. return;
  8121. AssemblyNode referencedAssembly = type.DeclaringModule as AssemblyNode;
  8122. if(referencedAssembly != null)
  8123. {
  8124. sb.Append(", ");
  8125. sb.Append(referencedAssembly.StrongName);
  8126. isAssemQualified = true;
  8127. }
  8128. }
  8129. void AppendSerializedTypeName(StringBuilder/*!*/ sb, TypeNode type, ref bool isAssemQualified)
  8130. {
  8131. if(type == null)
  8132. return;
  8133. string argTypeName = this.GetSerializedTypeName(type, ref isAssemQualified);
  8134. if(isAssemQualified)
  8135. sb.Append('[');
  8136. sb.Append(argTypeName);
  8137. if(isAssemQualified)
  8138. sb.Append(']');
  8139. }
  8140. /// <summary>
  8141. /// Return the name the constructor should have in this type node. By default, it's
  8142. /// the same as the name of the enclosing type node, but it can be different in e.g.
  8143. /// extensions in Extensible Sing#
  8144. /// </summary>
  8145. public virtual Identifier ConstructorName
  8146. {
  8147. get
  8148. {
  8149. if(this.constructorName == null)
  8150. {
  8151. Identifier id = this.Name;
  8152. if(this.IsNormalized && this.IsGeneric)
  8153. id = Identifier.For(this.GetUnmangledNameWithoutTypeParameters());
  8154. this.constructorName = id;
  8155. }
  8156. return this.constructorName;
  8157. }
  8158. }
  8159. private Identifier constructorName;
  8160. /// <summary>True if the type is an abstract class or an interface.</summary>
  8161. public virtual bool IsAbstract
  8162. {
  8163. get
  8164. {
  8165. return (this.Flags & TypeFlags.Abstract) != 0;
  8166. }
  8167. }
  8168. public override bool IsAssembly
  8169. {
  8170. get
  8171. {
  8172. TypeFlags visibility = this.Flags & TypeFlags.VisibilityMask;
  8173. return visibility == TypeFlags.NotPublic || visibility == TypeFlags.NestedAssembly;
  8174. }
  8175. }
  8176. public override bool IsCompilerControlled
  8177. {
  8178. get { return false; }
  8179. }
  8180. public override bool IsFamily
  8181. {
  8182. get { return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedFamily; }
  8183. }
  8184. public override bool IsFamilyAndAssembly
  8185. {
  8186. get { return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedFamANDAssem; }
  8187. }
  8188. public override bool IsFamilyOrAssembly
  8189. {
  8190. get { return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedFamORAssem; }
  8191. }
  8192. protected bool isGeneric;
  8193. /// <summary>True if this type is a template conforming to the rules of a generic type in the CLR.</summary>
  8194. public virtual bool IsGeneric
  8195. {
  8196. get
  8197. {
  8198. return this.isGeneric;
  8199. }
  8200. set
  8201. {
  8202. this.isGeneric = value;
  8203. }
  8204. }
  8205. public virtual bool IsNestedAssembly
  8206. {
  8207. get { return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedAssembly; }
  8208. }
  8209. public virtual bool IsNestedFamily
  8210. {
  8211. get { return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedFamily; }
  8212. }
  8213. public virtual bool IsNestedFamilyAndAssembly
  8214. {
  8215. get { return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedFamANDAssem; }
  8216. }
  8217. public virtual bool IsNestedInternal
  8218. {
  8219. get { return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedFamORAssem; }
  8220. }
  8221. public virtual bool IsNestedIn(TypeNode type)
  8222. {
  8223. for(TypeNode decType = this.DeclaringType; decType != null; decType = decType.DeclaringType)
  8224. {
  8225. if(decType == type)
  8226. return true;
  8227. }
  8228. return false;
  8229. }
  8230. public virtual bool IsNestedPublic
  8231. {
  8232. get { return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedPublic; }
  8233. }
  8234. public virtual bool IsNonPublic
  8235. {
  8236. get { return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NotPublic; }
  8237. }
  8238. protected bool isNormalized;
  8239. /// <summary>
  8240. /// 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
  8241. /// from CLR module or assembly. Such a node can be written out as compiled code to an assembly or module without further processing.
  8242. /// </summary>
  8243. public virtual bool IsNormalized
  8244. {
  8245. get
  8246. {
  8247. if(this.isNormalized)
  8248. return true;
  8249. if(this.DeclaringModule == null)
  8250. return false;
  8251. return this.isNormalized = this.DeclaringModule.IsNormalized;
  8252. }
  8253. set
  8254. {
  8255. this.isNormalized = value;
  8256. }
  8257. }
  8258. public override bool IsPrivate
  8259. {
  8260. get { return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedPrivate; }
  8261. }
  8262. /// <summary>True if values of this type can be compared directly in CLR IL instructions.</summary>
  8263. public virtual bool IsPrimitiveComparable
  8264. {
  8265. get
  8266. {
  8267. switch(this.typeCode)
  8268. {
  8269. case ElementType.Boolean:
  8270. case ElementType.Char:
  8271. case ElementType.Int8:
  8272. case ElementType.Int16:
  8273. case ElementType.Int32:
  8274. case ElementType.Int64:
  8275. case ElementType.IntPtr:
  8276. case ElementType.UInt8:
  8277. case ElementType.UInt16:
  8278. case ElementType.UInt32:
  8279. case ElementType.UInt64:
  8280. case ElementType.UIntPtr:
  8281. case ElementType.Single:
  8282. case ElementType.Double:
  8283. return true;
  8284. default:
  8285. return !(this is Struct) || this is EnumNode || this is Pointer;
  8286. }
  8287. }
  8288. }
  8289. /// <summary>True if values of this type are integers that can be processed by CLR IL instructions.</summary>
  8290. public virtual bool IsPrimitiveInteger
  8291. {
  8292. get
  8293. {
  8294. switch(this.typeCode)
  8295. {
  8296. case ElementType.Int8:
  8297. case ElementType.Int16:
  8298. case ElementType.Int32:
  8299. case ElementType.Int64:
  8300. case ElementType.IntPtr:
  8301. case ElementType.UInt8:
  8302. case ElementType.UInt16:
  8303. case ElementType.UInt32:
  8304. case ElementType.UInt64:
  8305. case ElementType.UIntPtr:
  8306. return true;
  8307. default:
  8308. return false;
  8309. }
  8310. }
  8311. }
  8312. /// <summary>True if values of this type are integers or floating point numbers that can be processed by CLR IL instructions.</summary>
  8313. public virtual bool IsPrimitiveNumeric
  8314. {
  8315. get
  8316. {
  8317. switch(this.typeCode)
  8318. {
  8319. case ElementType.Int8:
  8320. case ElementType.Int16:
  8321. case ElementType.Int32:
  8322. case ElementType.Int64:
  8323. case ElementType.IntPtr:
  8324. case ElementType.UInt8:
  8325. case ElementType.UInt16:
  8326. case ElementType.UInt32:
  8327. case ElementType.UInt64:
  8328. case ElementType.UIntPtr:
  8329. case ElementType.Single:
  8330. case ElementType.Double:
  8331. return true;
  8332. default:
  8333. return false;
  8334. }
  8335. }
  8336. }
  8337. /// <summary>True if values of this type are unsigned integers that can be processed by CLR IL instructions.</summary>
  8338. public virtual bool IsPrimitiveUnsignedInteger
  8339. {
  8340. get
  8341. {
  8342. switch(this.typeCode)
  8343. {
  8344. case ElementType.UInt8:
  8345. case ElementType.UInt16:
  8346. case ElementType.UInt32:
  8347. case ElementType.UInt64:
  8348. case ElementType.UIntPtr:
  8349. return true;
  8350. default:
  8351. return false;
  8352. }
  8353. }
  8354. }
  8355. public override bool IsPublic
  8356. {
  8357. get
  8358. {
  8359. TypeFlags visibility = this.Flags & TypeFlags.VisibilityMask;
  8360. return visibility == TypeFlags.Public || visibility == TypeFlags.NestedPublic;
  8361. }
  8362. }
  8363. /// <summary>True if values of this type can be processed by CLR IL instructions.</summary>
  8364. public virtual bool IsPrimitive
  8365. {
  8366. get
  8367. {
  8368. switch(this.typeCode)
  8369. {
  8370. case ElementType.Boolean:
  8371. case ElementType.Char:
  8372. case ElementType.Double:
  8373. case ElementType.Int16:
  8374. case ElementType.Int32:
  8375. case ElementType.Int64:
  8376. case ElementType.Int8:
  8377. case ElementType.IntPtr:
  8378. case ElementType.Single:
  8379. case ElementType.String:
  8380. case ElementType.UInt16:
  8381. case ElementType.UInt32:
  8382. case ElementType.UInt64:
  8383. case ElementType.UInt8:
  8384. case ElementType.UIntPtr:
  8385. return true;
  8386. default:
  8387. return false;
  8388. }
  8389. }
  8390. }
  8391. /// <summary>True if the type cannot be derived from.</summary>
  8392. public virtual bool IsSealed
  8393. {
  8394. get
  8395. {
  8396. return (this.Flags & TypeFlags.Sealed) != 0;
  8397. }
  8398. }
  8399. public override bool IsSpecialName
  8400. {
  8401. get { return (this.Flags & TypeFlags.SpecialName) != 0; }
  8402. }
  8403. public override bool IsStatic
  8404. {
  8405. get { return true; }
  8406. }
  8407. /// <summary>True if the identity of the type depends on its structure rather than its name.
  8408. /// Arrays, pointers and generic type instances are examples of such types.</summary>
  8409. public virtual bool IsStructural
  8410. {
  8411. get
  8412. {
  8413. return this.Template != null;
  8414. }
  8415. }
  8416. /// <summary>True if the type serves as a parameter to a type template.</summary>
  8417. public virtual bool IsTemplateParameter
  8418. {
  8419. get
  8420. {
  8421. return false;
  8422. }
  8423. }
  8424. /// <summary>True if the type is a value type containing only fields of unmanaged types.</summary>
  8425. public virtual bool IsUnmanaged
  8426. {
  8427. get
  8428. {
  8429. return false;
  8430. }
  8431. }
  8432. /// <summary>A list of the types that contribute to the structure of a structural type.</summary>
  8433. public virtual TypeNodeList StructuralElementTypes
  8434. {
  8435. get
  8436. {
  8437. TypeNodeList result = this.TemplateArguments;
  8438. if(result != null && result.Count > 0)
  8439. return result;
  8440. return this.TemplateParameters;
  8441. }
  8442. }
  8443. /// <summary>True if values of this type are unsigned integers that can be processed by CLR IL instructions.</summary>
  8444. public virtual bool IsUnsignedPrimitiveNumeric
  8445. {
  8446. get
  8447. {
  8448. switch(this.typeCode)
  8449. {
  8450. case ElementType.UInt8:
  8451. case ElementType.UInt16:
  8452. case ElementType.UInt32:
  8453. case ElementType.UInt64:
  8454. case ElementType.UIntPtr:
  8455. return true;
  8456. default:
  8457. return false;
  8458. }
  8459. }
  8460. }
  8461. /// <summary>True if instances of this type have no identity other than their value and are copied upon assignment.</summary>
  8462. public virtual bool IsValueType
  8463. {
  8464. get
  8465. {
  8466. switch(this.NodeType)
  8467. {
  8468. case NodeType.EnumNode:
  8469. case NodeType.ConstrainedType:
  8470. case NodeType.TupleType:
  8471. case NodeType.TypeAlias:
  8472. case NodeType.TypeIntersection:
  8473. case NodeType.TypeUnion:
  8474. return true;
  8475. case NodeType.Struct:
  8476. return true;
  8477. default:
  8478. return false;
  8479. }
  8480. }
  8481. }
  8482. /// <summary>
  8483. /// True if underlying type (modulo type modifiers) is a pointer type (Pointer)
  8484. /// </summary>
  8485. public virtual bool IsPointerType
  8486. {
  8487. get { return false; }
  8488. }
  8489. public override bool IsVisibleOutsideAssembly
  8490. {
  8491. get
  8492. {
  8493. if(this.DeclaringType != null && !this.DeclaringType.IsVisibleOutsideAssembly)
  8494. return false;
  8495. switch(this.Flags & TypeFlags.VisibilityMask)
  8496. {
  8497. case TypeFlags.Public:
  8498. case TypeFlags.NestedPublic:
  8499. return true;
  8500. case TypeFlags.NestedFamily:
  8501. case TypeFlags.NestedFamORAssem:
  8502. return this.DeclaringType != null && !this.DeclaringType.IsSealed;
  8503. default:
  8504. return false;
  8505. }
  8506. }
  8507. }
  8508. // This field stores those members declared syntactically within
  8509. // this type node. (Under Extended Sing#, additional members can
  8510. // be logically part of a type node but declared in a separate
  8511. // syntactic type node.)
  8512. protected internal MemberList members;
  8513. protected volatile internal bool membersBeingPopulated;
  8514. /// <summary>
  8515. /// The list of members contained inside this type, by default ignoring any extensions of this type.
  8516. /// (Subclasses in the Extensible Sing# dialect override this to include members of visible extensions.)
  8517. /// If the value of members is null and the value of ProvideTypeMembers is not null, the
  8518. /// TypeMemberProvider delegate is called to fill in the value of this property.
  8519. /// </summary>
  8520. public virtual MemberList Members
  8521. {
  8522. get
  8523. {
  8524. if(this.members == null || this.membersBeingPopulated)
  8525. if(this.ProvideTypeMembers != null && this.ProviderHandle != null)
  8526. {
  8527. lock(Module.GlobalLock)
  8528. {
  8529. if(this.members == null)
  8530. {
  8531. this.membersBeingPopulated = true;
  8532. this.ProvideTypeMembers(this, this.ProviderHandle);
  8533. this.membersBeingPopulated = false;
  8534. }
  8535. }
  8536. }
  8537. else
  8538. this.members = new MemberList();
  8539. return this.members;
  8540. }
  8541. set
  8542. {
  8543. this.members = value;
  8544. this.memberCount = 0;
  8545. this.memberTable = null;
  8546. this.constructors = null;
  8547. this.defaultMembers = null;
  8548. this.explicitCoercionFromTable = null;
  8549. this.explicitCoercionMethods = null;
  8550. this.explicitCoercionToTable = null;
  8551. this.implicitCoercionFromTable = null;
  8552. this.implicitCoercionMethods = null;
  8553. this.implicitCoercionToTable = null;
  8554. this.opFalse = null;
  8555. this.opTrue = null;
  8556. }
  8557. }
  8558. protected TypeNode template;
  8559. /// <summary>The (generic) type template from which this type was instantiated. Null if this is not a (generic) type template instance.</summary>
  8560. public virtual TypeNode Template
  8561. {
  8562. get
  8563. {
  8564. TypeNode result = this.template;
  8565. if(result == null)
  8566. {
  8567. if(this.isGeneric || TargetPlatform.GenericTypeNamesMangleChar != '_')
  8568. return null;
  8569. AttributeList attributes = this.Attributes;
  8570. lock(this)
  8571. {
  8572. if(this.template != null)
  8573. {
  8574. if(this.template == TypeNode.NotSpecified)
  8575. return null;
  8576. return this.template;
  8577. }
  8578. if(result == null)
  8579. this.template = TypeNode.NotSpecified;
  8580. }
  8581. }
  8582. else if(result == TypeNode.NotSpecified)
  8583. return null;
  8584. return result;
  8585. }
  8586. set
  8587. {
  8588. this.template = value;
  8589. }
  8590. }
  8591. public TypeNode TemplateExpression;
  8592. protected TypeNodeList templateArguments;
  8593. /// <summary>The arguments used when this (generic) type template instance was instantiated.</summary>
  8594. public virtual TypeNodeList TemplateArguments
  8595. {
  8596. get
  8597. {
  8598. if(this.template == null)
  8599. {
  8600. TypeNode templ = this.Template; //Will fill in the arguments
  8601. if(templ != null)
  8602. templ = null;
  8603. }
  8604. return this.templateArguments;
  8605. }
  8606. set
  8607. {
  8608. this.templateArguments = value;
  8609. }
  8610. }
  8611. public TypeNodeList TemplateArgumentExpressions;
  8612. internal TypeNodeList consolidatedTemplateArguments;
  8613. public virtual TypeNodeList ConsolidatedTemplateArguments
  8614. {
  8615. get
  8616. {
  8617. if(this.consolidatedTemplateArguments == null)
  8618. this.consolidatedTemplateArguments = this.GetConsolidatedTemplateArguments();
  8619. return this.consolidatedTemplateArguments;
  8620. }
  8621. set
  8622. {
  8623. this.consolidatedTemplateArguments = value;
  8624. }
  8625. }
  8626. private void AddTemplateParametersFromAttributeEncoding(TypeNodeList result)
  8627. {
  8628. }
  8629. internal TypeNodeList templateParameters;
  8630. /// <summary>The type parameters of this type. Null if this type is not a (generic) type template.</summary>
  8631. public virtual TypeNodeList TemplateParameters
  8632. {
  8633. get
  8634. {
  8635. TypeNodeList result = this.templateParameters;
  8636. if(result == null)
  8637. {
  8638. if(this.isGeneric || TargetPlatform.GenericTypeNamesMangleChar != '_')
  8639. return null; //Can happen when this is nested in a generic type
  8640. TypeNodeList nestedTypes = this.NestedTypes;
  8641. lock(this)
  8642. {
  8643. if((result = this.templateParameters) != null)
  8644. return result.Count == 0 ? null : result;
  8645. result = new TypeNodeList();
  8646. for(int i = 0, n = nestedTypes == null ? 0 : nestedTypes.Count; i < n; i++)
  8647. {
  8648. TypeNode nt = nestedTypes[i];
  8649. if(nt == null)
  8650. continue;
  8651. if(nt is MethodTypeParameter)
  8652. continue;
  8653. if(nt.NodeType == NodeType.TypeParameter || nt.NodeType == NodeType.ClassParameter)
  8654. result.Add(nt);
  8655. }
  8656. this.AddTemplateParametersFromAttributeEncoding(result);
  8657. this.TemplateParameters = result;
  8658. }
  8659. }
  8660. if(result.Count == 0)
  8661. return null;
  8662. return result;
  8663. }
  8664. set
  8665. {
  8666. if(value == null)
  8667. {
  8668. if(this.templateParameters == null)
  8669. return;
  8670. if(this.templateParameters.Count > 0)
  8671. value = new TypeNodeList();
  8672. }
  8673. this.templateParameters = value;
  8674. }
  8675. }
  8676. protected internal TypeNodeList consolidatedTemplateParameters;
  8677. public virtual TypeNodeList ConsolidatedTemplateParameters
  8678. {
  8679. get
  8680. {
  8681. if(this.consolidatedTemplateParameters == null)
  8682. this.consolidatedTemplateParameters = this.GetConsolidatedTemplateParameters();
  8683. return this.consolidatedTemplateParameters;
  8684. }
  8685. set
  8686. {
  8687. this.consolidatedTemplateParameters = value;
  8688. }
  8689. }
  8690. internal ElementType typeCode = ElementType.Class;
  8691. /// <summary>The System.TypeCode value that Convert.GetTypeCode will return pass an instance of this type as parameter.</summary>
  8692. public virtual System.TypeCode TypeCode
  8693. {
  8694. get
  8695. {
  8696. switch(this.typeCode)
  8697. {
  8698. case ElementType.Boolean:
  8699. return System.TypeCode.Boolean;
  8700. case ElementType.Char:
  8701. return System.TypeCode.Char;
  8702. case ElementType.Double:
  8703. return System.TypeCode.Double;
  8704. case ElementType.Int16:
  8705. return System.TypeCode.Int16;
  8706. case ElementType.Int32:
  8707. return System.TypeCode.Int32;
  8708. case ElementType.Int64:
  8709. return System.TypeCode.Int64;
  8710. case ElementType.Int8:
  8711. return System.TypeCode.SByte;
  8712. case ElementType.Single:
  8713. return System.TypeCode.Single;
  8714. case ElementType.UInt16:
  8715. return System.TypeCode.UInt16;
  8716. case ElementType.UInt32:
  8717. return System.TypeCode.UInt32;
  8718. case ElementType.UInt64:
  8719. return System.TypeCode.UInt64;
  8720. case ElementType.UInt8:
  8721. return System.TypeCode.Byte;
  8722. case ElementType.Void:
  8723. return System.TypeCode.Empty;
  8724. default:
  8725. if(this == CoreSystemTypes.String)
  8726. return System.TypeCode.String;
  8727. if(this == CoreSystemTypes.Decimal)
  8728. return System.TypeCode.Decimal;
  8729. if(this == CoreSystemTypes.DateTime)
  8730. return System.TypeCode.DateTime;
  8731. if(this == CoreSystemTypes.DBNull)
  8732. return System.TypeCode.DBNull;
  8733. return System.TypeCode.Object;
  8734. }
  8735. }
  8736. }
  8737. private readonly static TypeNode NotSpecified = new Class();
  8738. protected internal TrivialHashtableUsingWeakReferences structurallyEquivalentMethod;
  8739. /// <summary>
  8740. /// Returns the methods of an abstract type that have been left unimplemented. Includes methods inherited from
  8741. /// base classes and interfaces, and methods from any (known) extensions.
  8742. /// </summary>
  8743. /// <param name="result">A method list to which the abstract methods must be appended.</param>
  8744. public virtual void GetAbstractMethods(MethodList/*!*/ result)
  8745. {
  8746. if(!this.IsAbstract)
  8747. return;
  8748. //For each interface, get abstract methods and keep those that are not implemented by this class or a base class
  8749. InterfaceList interfaces = this.Interfaces;
  8750. for(int i = 0, n = interfaces == null ? 0 : interfaces.Count; i < n; i++)
  8751. {
  8752. Interface iface = interfaces[i];
  8753. if(iface == null)
  8754. continue;
  8755. MemberList imembers = iface.Members;
  8756. for(int j = 0, m = imembers == null ? 0 : imembers.Count; j < m; j++)
  8757. {
  8758. Method meth = imembers[j] as Method;
  8759. if(meth == null)
  8760. continue;
  8761. if(this.ImplementsExplicitly(meth))
  8762. continue;
  8763. if(this.ImplementsMethod(meth, true))
  8764. continue;
  8765. result.Add(meth);
  8766. }
  8767. }
  8768. }
  8769. protected internal TrivialHashtable szArrayTypes;
  8770. /// <summary>
  8771. /// Returns a type representing an array whose elements are of this type. Will always return the same instance for the same rank.
  8772. /// </summary>
  8773. /// <param name="rank">The number of dimensions of the array.</param>
  8774. public virtual ArrayType/*!*/ GetArrayType(int rank)
  8775. {
  8776. return this.GetArrayType(rank, false);
  8777. }
  8778. public virtual ArrayType/*!*/ GetArrayType(int rank, bool lowerBoundIsUnknown)
  8779. {
  8780. if(rank > 1 || lowerBoundIsUnknown)
  8781. return this.GetArrayType(rank, 0, 0, new int[0], new int[0]);
  8782. if(this.szArrayTypes == null)
  8783. this.szArrayTypes = new TrivialHashtable();
  8784. ArrayType result = (ArrayType)this.szArrayTypes[rank];
  8785. if(result != null)
  8786. return result;
  8787. lock(this)
  8788. {
  8789. result = (ArrayType)this.szArrayTypes[rank];
  8790. if(result != null)
  8791. return result;
  8792. this.szArrayTypes[rank] = result = new ArrayType(this, 1);
  8793. result.Flags &= ~TypeFlags.VisibilityMask;
  8794. result.Flags |= this.Flags & TypeFlags.VisibilityMask;
  8795. return result;
  8796. }
  8797. }
  8798. protected internal TrivialHashtable arrayTypes;
  8799. /// <summary>
  8800. /// 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.
  8801. /// </summary>
  8802. /// <param name="rank">The number of dimensions of the array.</param>
  8803. /// <param name="sizes">The size of each dimension.</param>
  8804. /// <param name="loBounds">The lower bound for indices. Defaults to zero.</param>
  8805. public virtual ArrayType/*!*/ GetArrayType(int rank, int[] sizes, int[] loBounds)
  8806. {
  8807. 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);
  8808. }
  8809. internal ArrayType/*!*/ GetArrayType(int rank, int numSizes, int numLoBounds, int[]/*!*/ sizes, int[]/*!*/ loBounds)
  8810. {
  8811. if(this.arrayTypes == null)
  8812. this.arrayTypes = new TrivialHashtable();
  8813. StringBuilder sb = new StringBuilder(rank * 5);
  8814. for(int i = 0; i < rank; i++)
  8815. {
  8816. if(i < numLoBounds)
  8817. sb.Append(loBounds[i]);
  8818. else
  8819. sb.Append('0');
  8820. if(i < numSizes) { sb.Append(':'); sb.Append(sizes[i]); }
  8821. sb.Append(',');
  8822. }
  8823. Identifier id = Identifier.For(sb.ToString());
  8824. ArrayType result = (ArrayType)this.arrayTypes[id.UniqueIdKey];
  8825. if(result != null)
  8826. return result;
  8827. lock(this)
  8828. {
  8829. result = (ArrayType)this.arrayTypes[id.UniqueIdKey];
  8830. if(result != null)
  8831. return result;
  8832. if(loBounds == null)
  8833. loBounds = new int[0];
  8834. this.arrayTypes[id.UniqueIdKey] = result = new ArrayType(this, rank, sizes, loBounds);
  8835. result.Flags &= ~TypeFlags.VisibilityMask;
  8836. result.Flags |= this.Flags & TypeFlags.VisibilityMask;
  8837. return result;
  8838. }
  8839. }
  8840. protected internal MemberList constructors;
  8841. public virtual MemberList GetConstructors()
  8842. {
  8843. if(this.Members.Count != this.memberCount)
  8844. this.constructors = null;
  8845. if(this.constructors != null)
  8846. return this.constructors;
  8847. lock(this)
  8848. {
  8849. if(this.constructors != null)
  8850. return this.constructors;
  8851. return this.constructors = TypeNode.WeedOutNonSpecialMethods(this.GetMembersNamed(StandardIds.Ctor), MethodFlags.RTSpecialName);
  8852. }
  8853. }
  8854. /// <summary>
  8855. /// Returns the constructor with the specified parameter types. Returns null if this type has no such constructor.
  8856. /// </summary>
  8857. public virtual InstanceInitializer GetConstructor(params TypeNode[] types)
  8858. {
  8859. return (InstanceInitializer)GetMethod(this.GetConstructors(), types);
  8860. }
  8861. protected override Identifier GetDocumentationId()
  8862. {
  8863. if(this.DeclaringType == null)
  8864. return Identifier.For("T:" + this.FullName);
  8865. else
  8866. return Identifier.For(this.DeclaringType.DocumentationId + "." + this.Name);
  8867. }
  8868. internal virtual void AppendDocumentIdMangledName(StringBuilder/*!*/ sb, TypeNodeList methodTypeParameters, TypeNodeList typeParameters)
  8869. {
  8870. if(this.DeclaringType != null)
  8871. {
  8872. this.DeclaringType.AppendDocumentIdMangledName(sb, methodTypeParameters, typeParameters);
  8873. sb.Append('.');
  8874. sb.Append(this.GetUnmangledNameWithoutTypeParameters());
  8875. }
  8876. else
  8877. sb.Append(this.GetFullUnmangledNameWithoutTypeParameters());
  8878. TypeNodeList templateArguments = this.TemplateArguments;
  8879. int n = templateArguments == null ? 0 : templateArguments.Count;
  8880. if(n == 0)
  8881. return;
  8882. sb.Append('{');
  8883. for(int i = 0; i < n; i++)
  8884. {
  8885. //^ assert templateArguments != null;
  8886. TypeNode templArg = templateArguments[i];
  8887. if(templArg == null)
  8888. continue;
  8889. templArg.AppendDocumentIdMangledName(sb, methodTypeParameters, typeParameters);
  8890. if(i < n - 1)
  8891. sb.Append(',');
  8892. }
  8893. sb.Append('}');
  8894. }
  8895. internal TrivialHashtable modifierTable;
  8896. internal TypeNode/*!*/ GetModified(TypeNode/*!*/ modifierType, bool optionalModifier)
  8897. {
  8898. if(this.modifierTable == null)
  8899. this.modifierTable = new TrivialHashtable();
  8900. TypeNode result = (TypeNode)this.modifierTable[modifierType.UniqueKey];
  8901. if(result != null)
  8902. return result;
  8903. result = optionalModifier ? (TypeNode)new OptionalModifier(modifierType, this) : (TypeNode)new RequiredModifier(modifierType, this);
  8904. this.modifierTable[modifierType.UniqueKey] = result;
  8905. return result;
  8906. }
  8907. public virtual TypeNode/*!*/ GetGenericTemplateInstance(Module/*!*/ module, TypeNodeList/*!*/ consolidatedArguments)
  8908. {
  8909. if(this.DeclaringType == null)
  8910. return this.GetTemplateInstance(module, null, null, consolidatedArguments);
  8911. TypeNodeList myArgs = this.GetOwnTemplateArguments(consolidatedArguments);
  8912. if(myArgs == consolidatedArguments)
  8913. return this.GetTemplateInstance(module, null, this.DeclaringType, consolidatedArguments);
  8914. int n = consolidatedArguments.Count;
  8915. int m = myArgs == null ? 0 : myArgs.Count;
  8916. int k = n - m;
  8917. Debug.Assert(k > 0);
  8918. TypeNodeList parentArgs = new TypeNodeList();
  8919. for(int i = 0; i < k; i++)
  8920. parentArgs.Add(consolidatedArguments[i]);
  8921. TypeNode declaringType = this.DeclaringType.GetGenericTemplateInstance(module, parentArgs);
  8922. TypeNode nestedType = declaringType.GetNestedType(this.Name);
  8923. if(nestedType == null) { Debug.Fail("template declaring type dummy instance does not have a nested type corresponding to template"); nestedType = this; }
  8924. if(m == 0) { Debug.Assert(nestedType.template != null); return nestedType; }
  8925. return nestedType.GetTemplateInstance(module, null, declaringType, myArgs);
  8926. }
  8927. public virtual TypeNode/*!*/ GetTemplateInstance(Module module, params TypeNode[] typeArguments)
  8928. {
  8929. return this.GetTemplateInstance(module, null, null, new TypeNodeList(typeArguments));
  8930. }
  8931. protected virtual void TryToFindExistingInstance(Module/*!*/ module, TypeNode declaringType, TypeNodeList/*!*/ templateArguments, Identifier/*!*/ mangledName,
  8932. Identifier/*!*/ uniqueMangledName, out TypeNode result, out Identifier unusedMangledName)
  8933. {
  8934. unusedMangledName = null;
  8935. string mangledNameString = mangledName.Name;
  8936. int n = templateArguments.Count;
  8937. int tiCount = 0;
  8938. bool lookInReferencedAssemblies = TargetPlatform.GenericTypeNamesMangleChar != '`'; //REVIEW: huh? why not use IsGeneric?
  8939. result = module.GetStructurallyEquivalentType(this.Namespace == null ? Identifier.Empty : this.Namespace, mangledName, uniqueMangledName, lookInReferencedAssemblies);
  8940. if(this.IsGeneric)
  8941. {
  8942. if(result == null)
  8943. unusedMangledName = mangledName;
  8944. return;
  8945. }
  8946. while(result != null)
  8947. {
  8948. //Mangled name is the same. But mangling is not unique (types are not qualified with assemblies), so check for equality.
  8949. if(this == result.Template && (declaringType == result.DeclaringType || !this.IsGeneric))
  8950. {
  8951. bool goodMatch = (result.TemplateArguments != null || n == 0) && result.TemplateArguments.Count == n;
  8952. for(int i = 0; goodMatch && i < n; i++)
  8953. goodMatch = templateArguments[i] == result.TemplateArguments[i];
  8954. if(goodMatch)
  8955. return;
  8956. }
  8957. //Mangle some more
  8958. mangledName = new Identifier(mangledNameString + (++tiCount).ToString());
  8959. result = module.GetStructurallyEquivalentType(this.Namespace == null ? Identifier.Empty : this.Namespace, mangledName, null, lookInReferencedAssemblies);
  8960. }
  8961. if(result == null)
  8962. unusedMangledName = mangledName;
  8963. }
  8964. public virtual Identifier/*!*/ GetMangledTemplateInstanceName(TypeNodeList/*!*/ templateArguments, out Identifier/*!*/ uniqueMangledName, out bool notFullySpecialized)
  8965. {
  8966. StringBuilder mangledNameBuilder = new StringBuilder(this.Name.ToString());
  8967. StringBuilder uniqueMangledNameBuilder = new StringBuilder(this.Name.ToString());
  8968. uniqueMangledNameBuilder.Append(this.UniqueKey);
  8969. notFullySpecialized = false;
  8970. for(int i = 0, n = templateArguments.Count; i < n; i++)
  8971. {
  8972. if(i == 0) { mangledNameBuilder.Append('<'); uniqueMangledNameBuilder.Append('<'); }
  8973. TypeNode t = templateArguments[i];
  8974. if(t == null || t.Name == null)
  8975. continue;
  8976. if(TypeIsNotFullySpecialized(t))
  8977. notFullySpecialized = true;
  8978. mangledNameBuilder.Append(t.FullName);
  8979. uniqueMangledNameBuilder.Append(t.FullName);
  8980. uniqueMangledNameBuilder.Append(t.UniqueKey);
  8981. if(i < n - 1)
  8982. {
  8983. mangledNameBuilder.Append(',');
  8984. uniqueMangledNameBuilder.Append(',');
  8985. }
  8986. else
  8987. {
  8988. mangledNameBuilder.Append('>');
  8989. uniqueMangledNameBuilder.Append('>');
  8990. }
  8991. }
  8992. uniqueMangledName = Identifier.For(uniqueMangledNameBuilder.ToString());
  8993. return Identifier.For(mangledNameBuilder.ToString());
  8994. }
  8995. private static bool TypeIsNotFullySpecialized(TypeNode t)
  8996. {
  8997. TypeNode tt = TypeNode.StripModifiers(t);
  8998. //^ assert tt != null;
  8999. if(tt is TypeParameter || tt is ClassParameter || tt.IsNotFullySpecialized)
  9000. return true;
  9001. for(int j = 0, m = tt.StructuralElementTypes == null ? 0 : tt.StructuralElementTypes.Count; j < m; j++)
  9002. {
  9003. TypeNode et = tt.StructuralElementTypes[j];
  9004. if(et == null)
  9005. continue;
  9006. if(TypeIsNotFullySpecialized(et))
  9007. return true;
  9008. }
  9009. return false;
  9010. }
  9011. /// <summary>
  9012. /// Gets an instance for the given template arguments of this (generic) template type.
  9013. /// </summary>
  9014. /// <param name="referringType">The type in which the reference to the template instance occurs. If the template is not
  9015. /// generic, the instance becomes a nested type of the referring type so that it has the same access privileges as the
  9016. /// code referring to the instance.</param>
  9017. /// <param name="templateArguments">The template arguments.</param>
  9018. /// <returns>An instance of the template. Always the same instance for the same arguments.</returns>
  9019. public virtual TypeNode/*!*/ GetTemplateInstance(TypeNode referringType, params TypeNode[] templateArguments)
  9020. {
  9021. return this.GetTemplateInstance(referringType, new TypeNodeList(templateArguments));
  9022. }
  9023. /// <summary>
  9024. /// Gets an instance for the given template arguments of this (generic) template type.
  9025. /// </summary>
  9026. /// <param name="referringType">The type in which the reference to the template instance occurs. If the template is not
  9027. /// generic, the instance becomes a nested type of the referring type so that it has the same access privileges as the
  9028. /// code referring to the instance.</param>
  9029. /// <param name="templateArguments">The template arguments.</param>
  9030. /// <returns>An instance of the template. Always the same instance for the same arguments.</returns>
  9031. public virtual TypeNode/*!*/ GetTemplateInstance(TypeNode referringType, TypeNodeList templateArguments)
  9032. {
  9033. if(referringType == null)
  9034. return this;
  9035. Module module = referringType.DeclaringModule;
  9036. return this.GetTemplateInstance(module, referringType, this.DeclaringType, templateArguments);
  9037. }
  9038. class CachingModuleForGenericsInstances : Module
  9039. {
  9040. public override TypeNode GetStructurallyEquivalentType(Identifier ns, Identifier/*!*/ id, Identifier uniqueMangledName, bool lookInReferencedAssemblies)
  9041. {
  9042. if(uniqueMangledName == null)
  9043. return null;
  9044. return (TypeNode)this.StructurallyEquivalentType[uniqueMangledName.UniqueIdKey];
  9045. }
  9046. }
  9047. protected static Module/*!*/ cachingModuleForGenericInstances = new CachingModuleForGenericsInstances();
  9048. public virtual TypeNode/*!*/ GetTemplateInstance(Module module, TypeNode referringType, TypeNode declaringType, TypeNodeList templateArguments)
  9049. {
  9050. TypeNodeList templateParameters = this.TemplateParameters;
  9051. if(module == null || templateArguments == null || (declaringType == null && (templateParameters == null || templateParameters.Count == 0)))
  9052. return this;
  9053. if(this.IsGeneric)
  9054. {
  9055. referringType = null;
  9056. module = TypeNode.cachingModuleForGenericInstances;
  9057. }
  9058. bool notFullySpecialized;
  9059. Identifier/*!*/ uniqueMangledName;
  9060. Identifier mangledName = this.GetMangledTemplateInstanceName(templateArguments, out uniqueMangledName, out notFullySpecialized);
  9061. TypeNode result;
  9062. Identifier dummyId;
  9063. this.TryToFindExistingInstance(module, declaringType, templateArguments, mangledName, uniqueMangledName, out result, out dummyId);
  9064. if(result != null)
  9065. return result;
  9066. if(this.NewTemplateInstanceIsRecursive)
  9067. return this; //An instance of this template is trying to instantiate the template again
  9068. lock(Module.GlobalLock)
  9069. {
  9070. Identifier unusedMangledName;
  9071. this.TryToFindExistingInstance(module, declaringType, templateArguments, mangledName, uniqueMangledName, out result, out unusedMangledName);
  9072. if(result != null)
  9073. return result;
  9074. //^ assume unusedMangledName != null;
  9075. TypeNodeList consolidatedTemplateArguments =
  9076. declaringType == null ? templateArguments : declaringType.GetConsolidatedTemplateArguments(templateArguments);
  9077. Duplicator duplicator = new Duplicator(module, referringType);
  9078. duplicator.RecordOriginalAsTemplate = true;
  9079. duplicator.SkipBodies = true;
  9080. duplicator.TypesToBeDuplicated[this.UniqueKey] = this;
  9081. result = duplicator.VisitTypeNode(this, unusedMangledName, consolidatedTemplateArguments, this.Template == null ? this : this.Template, true);
  9082. //^ assume result != null;
  9083. if(module == this.DeclaringModule)
  9084. {
  9085. if(this.TemplateInstances == null)
  9086. this.TemplateInstances = new TypeNodeList();
  9087. this.TemplateInstances.Add(result);
  9088. }
  9089. result.Name = unusedMangledName;
  9090. result.Name.SourceContext = this.Name.SourceContext;
  9091. result.fullName = null;
  9092. if(this.IsGeneric)
  9093. result.DeclaringModule = this.DeclaringModule;
  9094. result.DeclaringType = this.IsGeneric || referringType == null ? declaringType : referringType;
  9095. result.Template = this;
  9096. result.templateParameters = new TypeNodeList();
  9097. result.consolidatedTemplateParameters = new TypeNodeList();
  9098. result.templateArguments = templateArguments;
  9099. result.consolidatedTemplateArguments = consolidatedTemplateArguments;
  9100. result.IsNotFullySpecialized = notFullySpecialized || (declaringType != null && declaringType.IsNotFullySpecialized);
  9101. module.StructurallyEquivalentType[unusedMangledName.UniqueIdKey] = result;
  9102. module.StructurallyEquivalentType[uniqueMangledName.UniqueIdKey] = result;
  9103. Specializer specializer = new Specializer(module, this.ConsolidatedTemplateParameters, consolidatedTemplateArguments);
  9104. specializer.VisitTypeNode(result);
  9105. TypeFlags visibility = this.Flags & TypeFlags.VisibilityMask;
  9106. for(int i = 0, m = templateArguments.Count; i < m; i++)
  9107. {
  9108. TypeNode t = templateArguments[i];
  9109. if(t == null)
  9110. continue;
  9111. if(t is TypeParameter || t is ClassParameter || t.IsNotFullySpecialized)
  9112. continue;
  9113. visibility = TypeNode.GetVisibilityIntersection(visibility, t.Flags & TypeFlags.VisibilityMask);
  9114. }
  9115. result.Flags &= ~TypeFlags.VisibilityMask;
  9116. result.Flags |= visibility;
  9117. if(this.IsGeneric)
  9118. return result;
  9119. return result;
  9120. }
  9121. }
  9122. protected virtual TypeNodeList GetConsolidatedTemplateArguments()
  9123. {
  9124. TypeNodeList typeArgs = this.TemplateArguments;
  9125. if(this.DeclaringType == null)
  9126. return typeArgs;
  9127. TypeNodeList result = this.DeclaringType.ConsolidatedTemplateArguments;
  9128. if(result == null)
  9129. {
  9130. if(this.DeclaringType.IsGeneric && this.DeclaringType.Template == null)
  9131. result = this.DeclaringType.ConsolidatedTemplateParameters;
  9132. if(result == null)
  9133. return typeArgs;
  9134. }
  9135. int n = (typeArgs == null) ? 0 : typeArgs.Count;
  9136. if(n == 0)
  9137. return result;
  9138. result = new TypeNodeList(result);
  9139. result.AddRange(typeArgs);
  9140. return result;
  9141. }
  9142. protected virtual TypeNodeList GetConsolidatedTemplateArguments(TypeNodeList typeArgs)
  9143. {
  9144. TypeNodeList result = this.ConsolidatedTemplateArguments;
  9145. if(result == null || result.Count == 0)
  9146. {
  9147. if(this.IsGeneric && this.Template == null)
  9148. result = this.ConsolidatedTemplateParameters;
  9149. else
  9150. return typeArgs;
  9151. }
  9152. int n = (typeArgs == null) ? 0 : typeArgs.Count;
  9153. if(n == 0)
  9154. return result;
  9155. //^ assert typeArgs != null;
  9156. result = new TypeNodeList(result);
  9157. result.AddRange(typeArgs);
  9158. return result;
  9159. }
  9160. protected virtual TypeNodeList GetConsolidatedTemplateParameters()
  9161. {
  9162. TypeNodeList typeParams = this.TemplateParameters;
  9163. TypeNode declaringType = this.DeclaringType;
  9164. if(declaringType == null)
  9165. return typeParams;
  9166. while(declaringType.Template != null)
  9167. declaringType = declaringType.Template;
  9168. TypeNodeList result = declaringType.ConsolidatedTemplateParameters;
  9169. if(result == null)
  9170. return typeParams;
  9171. int n = (typeParams == null) ? 0 : typeParams.Count;
  9172. if(n == 0)
  9173. return result;
  9174. result = new TypeNodeList(result);
  9175. result.AddRange(typeParams);
  9176. return result;
  9177. }
  9178. protected virtual TypeNodeList GetOwnTemplateArguments(TypeNodeList consolidatedTemplateArguments)
  9179. {
  9180. int n = this.TemplateParameters == null ? 0 : this.TemplateParameters.Count;
  9181. int m = consolidatedTemplateArguments == null ? 0 : consolidatedTemplateArguments.Count;
  9182. int k = m - n;
  9183. if(k <= 0)
  9184. return consolidatedTemplateArguments;
  9185. TypeNodeList result = new TypeNodeList();
  9186. if(consolidatedTemplateArguments != null)
  9187. for(int i = 0; i < n; i++)
  9188. result.Add(consolidatedTemplateArguments[i + k]);
  9189. return result;
  9190. }
  9191. protected internal Pointer pointerType;
  9192. public virtual Pointer/*!*/ GetPointerType()
  9193. {
  9194. Pointer result = this.pointerType;
  9195. if(result == null)
  9196. {
  9197. lock(this)
  9198. {
  9199. if(this.pointerType != null)
  9200. return this.pointerType;
  9201. result = this.pointerType = new Pointer(this);
  9202. result.Flags &= ~TypeFlags.VisibilityMask;
  9203. result.Flags |= this.Flags & TypeFlags.VisibilityMask;
  9204. result.DeclaringModule = this.DeclaringModule;
  9205. }
  9206. }
  9207. return result;
  9208. }
  9209. protected internal Reference referenceType;
  9210. public virtual Reference/*!*/ GetReferenceType()
  9211. {
  9212. Reference result = this.referenceType;
  9213. if(result == null)
  9214. {
  9215. lock(this)
  9216. {
  9217. if(this.referenceType != null)
  9218. return this.referenceType;
  9219. result = this.referenceType = new Reference(this);
  9220. result.Flags &= ~TypeFlags.VisibilityMask;
  9221. result.Flags |= this.Flags & TypeFlags.VisibilityMask;
  9222. result.DeclaringModule = this.DeclaringModule;
  9223. }
  9224. }
  9225. return result;
  9226. }
  9227. //^ [Microsoft.Contracts.SpecPublic]
  9228. protected internal TrivialHashtable memberTable;
  9229. protected internal int memberCount;
  9230. /// <summary>
  9231. /// Returns a list of all the members declared directly by this type with the specified name.
  9232. /// Returns an empty list if this type has no such members.
  9233. /// </summary>
  9234. public virtual MemberList/*!*/ GetMembersNamed(Identifier name)
  9235. {
  9236. if(name == null)
  9237. return new MemberList();
  9238. MemberList members = this.Members;
  9239. int n = members == null ? 0 : members.Count;
  9240. if(n != this.memberCount || this.memberTable == null)
  9241. this.UpdateMemberTable(n);
  9242. //^ assert this.memberTable != null;
  9243. MemberList result = (MemberList)this.memberTable[name.UniqueIdKey];
  9244. if(result == null)
  9245. {
  9246. lock(this)
  9247. {
  9248. result = (MemberList)this.memberTable[name.UniqueIdKey];
  9249. if(result != null)
  9250. return result;
  9251. result = new MemberList();
  9252. this.memberTable[name.UniqueIdKey] = result;
  9253. }
  9254. }
  9255. return result;
  9256. }
  9257. /// <summary>
  9258. /// Returns the first event declared by this type with the specified name.
  9259. /// Returns null if this type has no such event.
  9260. /// </summary>
  9261. public virtual Event GetEvent(Identifier name)
  9262. {
  9263. MemberList members = this.GetMembersNamed(name);
  9264. for(int i = 0, n = members.Count; i < n; i++)
  9265. {
  9266. Event ev = members[i] as Event;
  9267. if(ev != null)
  9268. return ev;
  9269. }
  9270. return null;
  9271. }
  9272. /// <summary>
  9273. /// Returns the first field declared by this type with the specified name. Returns null if this type has no such field.
  9274. /// </summary>
  9275. public virtual Field GetField(Identifier name)
  9276. {
  9277. MemberList members = this.GetMembersNamed(name);
  9278. for(int i = 0, n = members.Count; i < n; i++)
  9279. {
  9280. Field field = members[i] as Field;
  9281. if(field != null)
  9282. return field;
  9283. }
  9284. return null;
  9285. }
  9286. /// <summary>
  9287. /// Returns the first method declared by this type with the specified name and parameter types. Returns null if this type has no such method.
  9288. /// </summary>
  9289. /// <returns></returns>
  9290. public virtual Method GetMethod(Identifier name, params TypeNode[] types)
  9291. {
  9292. return GetMethod(this.GetMembersNamed(name), types);
  9293. }
  9294. private static Method GetMethod(MemberList members, params TypeNode[] types)
  9295. {
  9296. if(members == null)
  9297. return null;
  9298. int m = types == null ? 0 : types.Length;
  9299. TypeNodeList typeNodes = m == 0 ? null : new TypeNodeList(types);
  9300. for(int i = 0, n = members.Count; i < n; i++)
  9301. {
  9302. Method meth = members[i] as Method;
  9303. if(meth == null)
  9304. continue;
  9305. if(meth.ParameterTypesMatchStructurally(typeNodes))
  9306. return meth;
  9307. }
  9308. return null;
  9309. }
  9310. public Method GetMatchingMethod(Method method)
  9311. {
  9312. if(method == null || method.Name == null)
  9313. return null;
  9314. MemberList members = this.GetMembersNamed(method.Name);
  9315. for(int i = 0, n = members == null ? 0 : members.Count; i < n; i++)
  9316. {
  9317. Method m = members[i] as Method;
  9318. // !EFW - Bug fix for problem reported by SHarwell. Must compare type parameter counts too.
  9319. // If not, overloaded methods, one with and one without generic parameters, will be matched
  9320. // incorrectly.
  9321. if(m == null || !m.TypeParameterCountsMatch(method))
  9322. continue;
  9323. if(m.ParametersMatchStructurally(method.Parameters))
  9324. return m;
  9325. }
  9326. return null;
  9327. }
  9328. /// <summary>
  9329. /// Returns the first nested type declared by this type with the specified name. Returns null if this type has no such nested type.
  9330. /// </summary>
  9331. public virtual TypeNode GetNestedType(Identifier name)
  9332. {
  9333. if(name == null)
  9334. return null;
  9335. if(this.members != null)
  9336. {
  9337. MemberList members = this.GetMembersNamed(name);
  9338. for(int i = 0, n = members.Count; i < n; i++)
  9339. {
  9340. TypeNode type = members[i] as TypeNode;
  9341. if(type != null)
  9342. return type;
  9343. }
  9344. return null;
  9345. }
  9346. TypeNodeList nestedTypes = this.NestedTypes;
  9347. for(int i = 0, n = nestedTypes == null ? 0 : nestedTypes.Count; i < n; i++)
  9348. {
  9349. TypeNode type = nestedTypes[i];
  9350. if(type != null && type.Name.UniqueIdKey == name.UniqueIdKey)
  9351. return type;
  9352. }
  9353. return null;
  9354. }
  9355. protected internal TypeNodeList nestedTypes;
  9356. // !EFW - Yes, static. See below.
  9357. private static int recursionCounter;
  9358. public virtual TypeNodeList NestedTypes
  9359. {
  9360. get
  9361. {
  9362. // !EFW - Okay, this is a REALLY ugly hack but I couldn't think of any other way around it.
  9363. // If a type contains a nested type that itself implements a nested type from within the
  9364. // containing type (still with me?), this gets into an endless loop and eventually overflows
  9365. // the stack. The problem is, we can't just ignore all subsequent recursions or it can
  9366. // throw a different error about a missing template type later on. The trick is to let it
  9367. // recurse enough to get all of the information it needs but not enough to overflow the
  9368. // stack. The full test case worked at 9 levels of recursion so 20 should be more than
  9369. // enough for any case. It overflowed at 256 levels of recursion.
  9370. //
  9371. // The abbreviated example:
  9372. //
  9373. // public interface IConsumer {}
  9374. // public interface IConsumeContext<TMessage> {}
  9375. //
  9376. // public class Consumes<TMessage> where TMessage : class
  9377. // {
  9378. // public interface All : IConsumer
  9379. // {
  9380. // void Consume(TMessage message);
  9381. // }
  9382. //
  9383. // public interface Context : Consumes<IConsumeContext<TMessage>>.All
  9384. // {
  9385. // }
  9386. // }
  9387. //
  9388. // Note that this abbreviated example will overflow the stack but will not manifest the
  9389. // secondary "missing template type" error if the recursion count is too low. In case
  9390. // you're wondering, the full test case was the Mass Transit project on GitHub which was
  9391. // being used as a reference assembly by the person that reported the error.
  9392. //
  9393. if(recursionCounter > 20)
  9394. return null;
  9395. if(this.nestedTypes != null && (this.members == null || this.members.Count == this.memberCount))
  9396. return this.nestedTypes;
  9397. if(this.ProvideNestedTypes != null && this.ProviderHandle != null)
  9398. {
  9399. lock(Module.GlobalLock)
  9400. {
  9401. recursionCounter++;
  9402. this.ProvideNestedTypes(this, this.ProviderHandle);
  9403. recursionCounter--;
  9404. }
  9405. }
  9406. else
  9407. {
  9408. MemberList members = this.Members;
  9409. TypeNodeList nestedTypes = new TypeNodeList();
  9410. for(int i = 0, n = members == null ? 0 : members.Count; i < n; i++)
  9411. {
  9412. TypeNode nt = members[i] as TypeNode;
  9413. if(nt == null)
  9414. continue;
  9415. nestedTypes.Add(nt);
  9416. }
  9417. this.nestedTypes = nestedTypes;
  9418. }
  9419. return this.nestedTypes;
  9420. }
  9421. set
  9422. {
  9423. this.nestedTypes = value;
  9424. }
  9425. }
  9426. /// <summary>
  9427. /// Returns the first property declared by this type with the specified name and parameter types. Returns null if this type has no such property.
  9428. /// </summary>
  9429. public virtual Property GetProperty(Identifier name, params TypeNode[] types)
  9430. {
  9431. return GetProperty(this.GetMembersNamed(name), types);
  9432. }
  9433. private static Property GetProperty(MemberList members, params TypeNode[] types)
  9434. {
  9435. if(members == null)
  9436. return null;
  9437. int m = types == null ? 0 : types.Length;
  9438. TypeNodeList typeNodes = m == 0 ? null : new TypeNodeList(types);
  9439. for(int i = 0, n = members.Count; i < n; i++)
  9440. {
  9441. Property prop = members[i] as Property;
  9442. if(prop == null)
  9443. continue;
  9444. if(prop.ParameterTypesMatch(typeNodes))
  9445. return prop;
  9446. }
  9447. return null;
  9448. }
  9449. protected internal MemberList explicitCoercionMethods;
  9450. public virtual MemberList ExplicitCoercionMethods
  9451. {
  9452. get
  9453. {
  9454. if(this.Members.Count != this.memberCount)
  9455. this.explicitCoercionMethods = null;
  9456. if(this.explicitCoercionMethods != null)
  9457. return this.explicitCoercionMethods;
  9458. lock(this)
  9459. {
  9460. if(this.explicitCoercionMethods != null)
  9461. return this.explicitCoercionMethods;
  9462. return this.explicitCoercionMethods = TypeNode.WeedOutNonSpecialMethods(this.GetMembersNamed(StandardIds.opExplicit), MethodFlags.SpecialName);
  9463. }
  9464. }
  9465. }
  9466. protected internal MemberList implicitCoercionMethods;
  9467. public virtual MemberList ImplicitCoercionMethods
  9468. {
  9469. get
  9470. {
  9471. if(this.Members.Count != this.memberCount)
  9472. this.implicitCoercionMethods = null;
  9473. if(this.implicitCoercionMethods != null)
  9474. return this.implicitCoercionMethods;
  9475. lock(this)
  9476. {
  9477. if(this.implicitCoercionMethods != null)
  9478. return this.implicitCoercionMethods;
  9479. return this.implicitCoercionMethods = TypeNode.WeedOutNonSpecialMethods(this.GetMembersNamed(StandardIds.opImplicit), MethodFlags.SpecialName);
  9480. }
  9481. }
  9482. }
  9483. protected readonly static Method MethodDoesNotExist = new Method();
  9484. protected internal TrivialHashtable explicitCoercionFromTable;
  9485. public virtual Method GetExplicitCoercionFromMethod(TypeNode sourceType)
  9486. {
  9487. if(sourceType == null)
  9488. return null;
  9489. Method result = null;
  9490. if(this.explicitCoercionFromTable != null)
  9491. result = (Method)this.explicitCoercionFromTable[sourceType.UniqueKey];
  9492. if(result == TypeNode.MethodDoesNotExist)
  9493. return null;
  9494. if(result != null)
  9495. return result;
  9496. lock(this)
  9497. {
  9498. if(this.explicitCoercionFromTable != null)
  9499. result = (Method)this.explicitCoercionFromTable[sourceType.UniqueKey];
  9500. if(result == TypeNode.MethodDoesNotExist)
  9501. return null;
  9502. if(result != null)
  9503. return result;
  9504. MemberList coercions = this.ExplicitCoercionMethods;
  9505. for(int i = 0, n = coercions.Count; i < n; i++)
  9506. {
  9507. Method m = (Method)coercions[i];
  9508. if(sourceType == m.Parameters[0].Type) { result = m; break; }
  9509. }
  9510. if(this.explicitCoercionFromTable == null)
  9511. this.explicitCoercionFromTable = new TrivialHashtable();
  9512. if(result == null)
  9513. this.explicitCoercionFromTable[sourceType.UniqueKey] = TypeNode.MethodDoesNotExist;
  9514. else
  9515. this.explicitCoercionFromTable[sourceType.UniqueKey] = result;
  9516. return result;
  9517. }
  9518. }
  9519. protected internal TrivialHashtable explicitCoercionToTable;
  9520. public virtual Method GetExplicitCoercionToMethod(TypeNode targetType)
  9521. {
  9522. if(targetType == null)
  9523. return null;
  9524. Method result = null;
  9525. if(this.explicitCoercionToTable != null)
  9526. result = (Method)this.explicitCoercionToTable[targetType.UniqueKey];
  9527. if(result == TypeNode.MethodDoesNotExist)
  9528. return null;
  9529. if(result != null)
  9530. return result;
  9531. lock(this)
  9532. {
  9533. if(this.explicitCoercionToTable != null)
  9534. result = (Method)this.explicitCoercionToTable[targetType.UniqueKey];
  9535. if(result == TypeNode.MethodDoesNotExist)
  9536. return null;
  9537. if(result != null)
  9538. return result;
  9539. MemberList coercions = this.ExplicitCoercionMethods;
  9540. for(int i = 0, n = coercions.Count; i < n; i++)
  9541. {
  9542. Method m = (Method)coercions[i];
  9543. if(m.ReturnType == targetType) { result = m; break; }
  9544. }
  9545. if(this.explicitCoercionToTable == null)
  9546. this.explicitCoercionToTable = new TrivialHashtable();
  9547. if(result == null)
  9548. this.explicitCoercionToTable[targetType.UniqueKey] = TypeNode.MethodDoesNotExist;
  9549. else
  9550. this.explicitCoercionToTable[targetType.UniqueKey] = result;
  9551. }
  9552. return result;
  9553. }
  9554. protected internal TrivialHashtable implicitCoercionFromTable;
  9555. public virtual Method GetImplicitCoercionFromMethod(TypeNode sourceType)
  9556. {
  9557. if(sourceType == null)
  9558. return null;
  9559. Method result = null;
  9560. if(this.implicitCoercionFromTable != null)
  9561. result = (Method)this.implicitCoercionFromTable[sourceType.UniqueKey];
  9562. if(result == TypeNode.MethodDoesNotExist)
  9563. return null;
  9564. if(result != null)
  9565. return result;
  9566. lock(this)
  9567. {
  9568. if(this.implicitCoercionFromTable != null)
  9569. result = (Method)this.implicitCoercionFromTable[sourceType.UniqueKey];
  9570. if(result == TypeNode.MethodDoesNotExist)
  9571. return null;
  9572. if(result != null)
  9573. return result;
  9574. MemberList coercions = this.ImplicitCoercionMethods;
  9575. for(int i = 0, n = coercions.Count; i < n; i++)
  9576. {
  9577. Method m = (Method)coercions[i];
  9578. if(sourceType.IsStructurallyEquivalentTo(TypeNode.StripModifiers(m.Parameters[0].Type))) { result = m; break; }
  9579. }
  9580. if(this.implicitCoercionFromTable == null)
  9581. this.implicitCoercionFromTable = new TrivialHashtable();
  9582. if(result == null)
  9583. this.implicitCoercionFromTable[sourceType.UniqueKey] = TypeNode.MethodDoesNotExist;
  9584. else
  9585. this.implicitCoercionFromTable[sourceType.UniqueKey] = result;
  9586. return result;
  9587. }
  9588. }
  9589. protected internal TrivialHashtable implicitCoercionToTable;
  9590. public virtual Method GetImplicitCoercionToMethod(TypeNode targetType)
  9591. {
  9592. if(targetType == null)
  9593. return null;
  9594. Method result = null;
  9595. if(this.implicitCoercionToTable != null)
  9596. result = (Method)this.implicitCoercionToTable[targetType.UniqueKey];
  9597. if(result == TypeNode.MethodDoesNotExist)
  9598. return null;
  9599. if(result != null)
  9600. return result;
  9601. lock(this)
  9602. {
  9603. if(this.implicitCoercionToTable != null)
  9604. result = (Method)this.implicitCoercionToTable[targetType.UniqueKey];
  9605. if(result == TypeNode.MethodDoesNotExist)
  9606. return null;
  9607. if(result != null)
  9608. return result;
  9609. MemberList coercions = this.ImplicitCoercionMethods;
  9610. for(int i = 0, n = coercions.Count; i < n; i++)
  9611. {
  9612. Method m = (Method)coercions[i];
  9613. if(m.ReturnType == targetType) { result = m; break; }
  9614. }
  9615. if(this.implicitCoercionToTable == null)
  9616. this.implicitCoercionToTable = new TrivialHashtable();
  9617. if(result == null)
  9618. this.implicitCoercionToTable[targetType.UniqueKey] = TypeNode.MethodDoesNotExist;
  9619. else
  9620. this.implicitCoercionToTable[targetType.UniqueKey] = result;
  9621. return result;
  9622. }
  9623. }
  9624. protected Method opFalse;
  9625. public virtual Method GetOpFalse()
  9626. {
  9627. Method result = this.opFalse;
  9628. if(result == TypeNode.MethodDoesNotExist)
  9629. return null;
  9630. if(result != null)
  9631. return result;
  9632. MemberList members = this.Members; //evaluate for side effect
  9633. if(members != null)
  9634. members = null;
  9635. lock(this)
  9636. {
  9637. result = this.opFalse;
  9638. if(result == TypeNode.MethodDoesNotExist)
  9639. return null;
  9640. if(result != null)
  9641. return result;
  9642. TypeNode t = this;
  9643. while(t != null)
  9644. {
  9645. MemberList opFalses = t.GetMembersNamed(StandardIds.opFalse);
  9646. if(opFalses != null)
  9647. for(int i = 0, n = opFalses.Count; i < n; i++)
  9648. {
  9649. Method opFalse = opFalses[i] as Method;
  9650. if(opFalse == null)
  9651. continue;
  9652. if(!opFalse.IsSpecialName || !opFalse.IsStatic || !opFalse.IsPublic || opFalse.ReturnType != CoreSystemTypes.Boolean ||
  9653. opFalse.Parameters == null || opFalse.Parameters.Count != 1)
  9654. continue;
  9655. return this.opFalse = opFalse;
  9656. }
  9657. t = t.BaseType;
  9658. }
  9659. this.opFalse = TypeNode.MethodDoesNotExist;
  9660. return null;
  9661. }
  9662. }
  9663. protected Method opTrue;
  9664. public virtual Method GetOpTrue()
  9665. {
  9666. Method result = this.opTrue;
  9667. if(result == TypeNode.MethodDoesNotExist)
  9668. return null;
  9669. if(result != null)
  9670. return result;
  9671. MemberList members = this.Members; //evaluate for side effect
  9672. if(members != null)
  9673. members = null;
  9674. lock(this)
  9675. {
  9676. result = this.opTrue;
  9677. if(result == TypeNode.MethodDoesNotExist)
  9678. return null;
  9679. if(result != null)
  9680. return result;
  9681. TypeNode t = this;
  9682. while(t != null)
  9683. {
  9684. MemberList opTrues = t.GetMembersNamed(StandardIds.opTrue);
  9685. if(opTrues != null)
  9686. for(int i = 0, n = opTrues.Count; i < n; i++)
  9687. {
  9688. Method opTrue = opTrues[i] as Method;
  9689. if(opTrue == null)
  9690. continue;
  9691. if(!opTrue.IsSpecialName || !opTrue.IsStatic || !opTrue.IsPublic || opTrue.ReturnType != CoreSystemTypes.Boolean ||
  9692. opTrue.Parameters == null || opTrue.Parameters.Count != 1)
  9693. continue;
  9694. return this.opTrue = opTrue;
  9695. }
  9696. t = t.BaseType;
  9697. }
  9698. this.opTrue = TypeNode.MethodDoesNotExist;
  9699. return null;
  9700. }
  9701. }
  9702. private static Hashtable typeMap; //contains weak references
  9703. /// <summary>
  9704. /// Gets a TypeNode instance corresponding to the given System.Type instance.
  9705. /// </summary>
  9706. /// <param name="type">A runtime type.</param>
  9707. /// <returns>A TypeNode instance.</returns>
  9708. public static TypeNode GetTypeNode(System.Type type)
  9709. {
  9710. if(type == null)
  9711. return null;
  9712. Hashtable typeMap = TypeNode.typeMap;
  9713. if(typeMap == null)
  9714. TypeNode.typeMap = typeMap = Hashtable.Synchronized(new Hashtable());
  9715. TypeNode result = null;
  9716. WeakReference wr = (WeakReference)typeMap[type];
  9717. if(wr != null)
  9718. {
  9719. result = wr.Target as TypeNode;
  9720. if(result == Class.DoesNotExist)
  9721. return null;
  9722. if(result != null)
  9723. return result;
  9724. }
  9725. if(type.IsGenericType && !type.IsGenericTypeDefinition)
  9726. {
  9727. try
  9728. {
  9729. TypeNode template = TypeNode.GetTypeNode(type.GetGenericTypeDefinition());
  9730. if(template == null)
  9731. return null;
  9732. TypeNodeList templateArguments = new TypeNodeList();
  9733. foreach(Type arg in type.GetGenericArguments())
  9734. templateArguments.Add(TypeNode.GetTypeNode(arg));
  9735. return template.GetGenericTemplateInstance(template.DeclaringModule, templateArguments);
  9736. }
  9737. catch
  9738. {
  9739. //TODO: log error
  9740. return null;
  9741. }
  9742. }
  9743. if(type.IsGenericParameter)
  9744. {
  9745. try
  9746. {
  9747. int parIndx = type.GenericParameterPosition;
  9748. System.Reflection.MethodInfo mi = type.DeclaringMethod as System.Reflection.MethodInfo;
  9749. if(mi != null)
  9750. {
  9751. Method m = Method.GetMethod(mi);
  9752. if(m == null)
  9753. return null;
  9754. if(m.TemplateParameters != null && m.TemplateParameters.Count > parIndx)
  9755. return m.TemplateParameters[parIndx];
  9756. }
  9757. else
  9758. {
  9759. System.Type ti = type.DeclaringType;
  9760. TypeNode t = TypeNode.GetTypeNode(ti);
  9761. if(t == null)
  9762. return null;
  9763. if(t.TemplateParameters != null && t.TemplateParameters.Count > parIndx)
  9764. return t.TemplateParameters[parIndx];
  9765. }
  9766. return null;
  9767. }
  9768. catch
  9769. {
  9770. //TODO: log error
  9771. return null;
  9772. }
  9773. }
  9774. if(type.HasElementType)
  9775. {
  9776. TypeNode elemType = TypeNode.GetTypeNode(type.GetElementType());
  9777. if(elemType == null)
  9778. return null;
  9779. if(type.IsArray)
  9780. result = elemType.GetArrayType(type.GetArrayRank());
  9781. else if(type.IsByRef)
  9782. result = elemType.GetReferenceType();
  9783. else if(type.IsPointer)
  9784. result = elemType.GetPointerType();
  9785. else
  9786. {
  9787. Debug.Assert(false);
  9788. result = null;
  9789. }
  9790. }
  9791. else if(type.DeclaringType != null)
  9792. {
  9793. TypeNode dType = TypeNode.GetTypeNode(type.DeclaringType);
  9794. if(dType == null)
  9795. return null;
  9796. result = dType.GetNestedType(Identifier.For(type.Name));
  9797. }
  9798. else
  9799. {
  9800. AssemblyNode assem = AssemblyNode.GetAssembly(type.Assembly);
  9801. if(assem != null)
  9802. {
  9803. result = assem.GetType(Identifier.For(type.Namespace), Identifier.For(type.Name));
  9804. }
  9805. }
  9806. if(result == null)
  9807. typeMap[type] = new WeakReference(Class.DoesNotExist);
  9808. else
  9809. typeMap[type] = new WeakReference(result);
  9810. return result;
  9811. }
  9812. protected internal Type runtimeType;
  9813. /// <summary>
  9814. /// Gets a System.Type instance corresponding to this type. The assembly containin this type must be normalized
  9815. /// and must have a location on disk or must have been loaded via AssemblyNode.GetRuntimeAssembly.
  9816. /// </summary>
  9817. /// <returns>A System.Type instance. (A runtime type.)</returns>
  9818. public virtual Type GetRuntimeType()
  9819. {
  9820. if(this.runtimeType == null)
  9821. {
  9822. lock(this)
  9823. {
  9824. if(this.runtimeType != null)
  9825. return this.runtimeType;
  9826. if(this.IsGeneric && this.Template != null)
  9827. {
  9828. try
  9829. {
  9830. TypeNode rootTemplate = this.Template;
  9831. while(rootTemplate.Template != null)
  9832. rootTemplate = rootTemplate.Template;
  9833. Type genType = rootTemplate.GetRuntimeType();
  9834. if(genType == null)
  9835. return null;
  9836. TypeNodeList args = this.ConsolidatedTemplateArguments;
  9837. Type[] arguments = new Type[args.Count];
  9838. for(int i = 0; i < args.Count; i++)
  9839. arguments[i] = args[i].GetRuntimeType();
  9840. return genType.MakeGenericType(arguments);
  9841. }
  9842. catch
  9843. {
  9844. //TODO: add error to metadata import errors if type is imported
  9845. return null;
  9846. }
  9847. }
  9848. if(this.DeclaringType != null)
  9849. {
  9850. Type dt = this.DeclaringType.GetRuntimeType();
  9851. if(dt != null)
  9852. {
  9853. System.Reflection.BindingFlags flags = System.Reflection.BindingFlags.DeclaredOnly;
  9854. if(this.IsPublic)
  9855. flags |= System.Reflection.BindingFlags.Public;
  9856. else
  9857. flags |= System.Reflection.BindingFlags.NonPublic;
  9858. this.runtimeType = dt.GetNestedType(this.Name.ToString(), flags);
  9859. }
  9860. }
  9861. else if(this.DeclaringModule != null && this.DeclaringModule.IsNormalized && this.DeclaringModule.ContainingAssembly != null)
  9862. {
  9863. System.Reflection.Assembly runtimeAssembly = this.DeclaringModule.ContainingAssembly.GetRuntimeAssembly();
  9864. if(runtimeAssembly != null)
  9865. this.runtimeType = runtimeAssembly.GetType(this.FullName, false);
  9866. }
  9867. }
  9868. }
  9869. return this.runtimeType;
  9870. }
  9871. public static TypeFlags GetVisibilityIntersection(TypeFlags vis1, TypeFlags vis2)
  9872. {
  9873. switch(vis2)
  9874. {
  9875. case TypeFlags.Public:
  9876. case TypeFlags.NestedPublic:
  9877. return vis1;
  9878. case TypeFlags.NotPublic:
  9879. case TypeFlags.NestedAssembly:
  9880. switch(vis1)
  9881. {
  9882. case TypeFlags.Public:
  9883. return vis2;
  9884. case TypeFlags.NestedPublic:
  9885. case TypeFlags.NestedFamORAssem:
  9886. return TypeFlags.NestedAssembly;
  9887. case TypeFlags.NestedFamily:
  9888. return TypeFlags.NestedFamANDAssem;
  9889. default:
  9890. return vis1;
  9891. }
  9892. case TypeFlags.NestedFamANDAssem:
  9893. switch(vis1)
  9894. {
  9895. case TypeFlags.Public:
  9896. case TypeFlags.NestedPublic:
  9897. case TypeFlags.NestedFamORAssem:
  9898. case TypeFlags.NestedFamily:
  9899. return TypeFlags.NestedFamANDAssem;
  9900. default:
  9901. return vis1;
  9902. }
  9903. case TypeFlags.NestedFamORAssem:
  9904. switch(vis1)
  9905. {
  9906. case TypeFlags.Public:
  9907. case TypeFlags.NestedPublic:
  9908. return TypeFlags.NestedFamORAssem;
  9909. default:
  9910. return vis1;
  9911. }
  9912. case TypeFlags.NestedFamily:
  9913. switch(vis1)
  9914. {
  9915. case TypeFlags.Public:
  9916. case TypeFlags.NestedPublic:
  9917. case TypeFlags.NestedFamORAssem:
  9918. return TypeFlags.NestedFamily;
  9919. case TypeFlags.NestedAssembly:
  9920. return TypeFlags.NestedFamANDAssem;
  9921. default:
  9922. return vis1;
  9923. }
  9924. default:
  9925. return TypeFlags.NestedPrivate;
  9926. }
  9927. }
  9928. private TrivialHashtable explicitInterfaceImplementations;
  9929. public bool ImplementsExplicitly(Method method)
  9930. {
  9931. if(method == null)
  9932. return false;
  9933. TrivialHashtable explicitInterfaceImplementations = this.explicitInterfaceImplementations;
  9934. if(explicitInterfaceImplementations == null)
  9935. {
  9936. MemberList members = this.Members;
  9937. lock(this)
  9938. {
  9939. if((explicitInterfaceImplementations = this.explicitInterfaceImplementations) == null)
  9940. {
  9941. explicitInterfaceImplementations = this.explicitInterfaceImplementations = new TrivialHashtable();
  9942. for(int i = 0, n = members.Count; i < n; i++)
  9943. {
  9944. Method m = members[i] as Method;
  9945. if(m == null)
  9946. continue;
  9947. MethodList implementedInterfaceMethods = m.ImplementedInterfaceMethods;
  9948. if(implementedInterfaceMethods != null)
  9949. for(int j = 0, k = implementedInterfaceMethods.Count; j < k; j++)
  9950. {
  9951. Method im = implementedInterfaceMethods[j];
  9952. if(im == null)
  9953. continue;
  9954. explicitInterfaceImplementations[im.UniqueKey] = m;
  9955. }
  9956. }
  9957. }
  9958. }
  9959. }
  9960. return explicitInterfaceImplementations[method.UniqueKey] != null;
  9961. }
  9962. internal bool ImplementsMethod(Method meth, bool checkPublic)
  9963. {
  9964. return this.GetImplementingMethod(meth, checkPublic) != null;
  9965. }
  9966. public Method GetImplementingMethod(Method meth, bool checkPublic)
  9967. {
  9968. if(meth == null)
  9969. return null;
  9970. MemberList mems = this.GetMembersNamed(meth.Name);
  9971. for(int j = 0, m = mems == null ? 0 : mems.Count; j < m; j++)
  9972. {
  9973. Method locM = mems[j] as Method;
  9974. if(locM == null || !locM.IsVirtual || (checkPublic && !locM.IsPublic))
  9975. continue;
  9976. if((locM.ReturnType != meth.ReturnType && !(locM.ReturnType != null && locM.ReturnType.IsStructurallyEquivalentTo(meth.ReturnType))) ||
  9977. !locM.ParametersMatchStructurally(meth.Parameters))
  9978. continue;
  9979. return locM;
  9980. }
  9981. if(checkPublic && this.BaseType != null)
  9982. return this.BaseType.GetImplementingMethod(meth, true);
  9983. return null;
  9984. }
  9985. /// <summary>
  9986. /// 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),
  9987. /// 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,
  9988. /// or because this type and the target type are zero based single dimensional arrays with assignment compatible reference element types
  9989. /// </summary>
  9990. public virtual bool IsAssignableTo(TypeNode targetType)
  9991. {
  9992. if(this == CoreSystemTypes.Void)
  9993. return false;
  9994. if(targetType == this)
  9995. return true;
  9996. if(this == CoreSystemTypes.Object)
  9997. return false;
  9998. if(targetType == CoreSystemTypes.Object || this.IsStructurallyEquivalentTo(targetType) ||
  9999. this.BaseType != null && (this.BaseType.IsAssignableTo(targetType)))
  10000. return true;
  10001. if(this.BaseType != null && this.ConsolidatedTemplateParameters != null && this.BaseType.Template != null && this.BaseType.Template.IsAssignableTo(targetType))
  10002. return true; //When seeing if one template is assignable to another, be sure to strip off template instances along the inheritance chain
  10003. InterfaceList interfaces = this.Interfaces;
  10004. if(interfaces == null)
  10005. return false;
  10006. for(int i = 0, n = interfaces.Count; i < n; i++)
  10007. {
  10008. Interface iface = interfaces[i];
  10009. if(iface == null)
  10010. continue;
  10011. if(iface.IsAssignableTo(targetType))
  10012. return true;
  10013. if(iface.Template != null && this.ConsolidatedTemplateParameters != null && iface.Template.IsAssignableTo(targetType))
  10014. return true; //When seeing if one template is assignable to another, be sure to strip off template instances along the inheritance chain
  10015. }
  10016. return false;
  10017. }
  10018. /// <summary>
  10019. /// Returns true if this type is assignable to some instance of the given template.
  10020. /// </summary>
  10021. public virtual bool IsAssignableToInstanceOf(TypeNode targetTemplate)
  10022. {
  10023. if(this == CoreSystemTypes.Void || targetTemplate == null)
  10024. return false;
  10025. if(targetTemplate.IsStructurallyEquivalentTo(this.Template == null ? this : this.Template) ||
  10026. this.BaseType != null && (this.BaseType.IsAssignableToInstanceOf(targetTemplate) ||
  10027. this.BaseType.Template != null && this.BaseType.Template.IsAssignableToInstanceOf(targetTemplate)))
  10028. return true;
  10029. InterfaceList interfaces = this.Interfaces;
  10030. if(interfaces == null)
  10031. return false;
  10032. for(int i = 0, n = interfaces.Count; i < n; i++)
  10033. {
  10034. Interface iface = interfaces[i];
  10035. if(iface == null)
  10036. continue;
  10037. if(iface.IsAssignableToInstanceOf(targetTemplate))
  10038. return true;
  10039. }
  10040. return false;
  10041. }
  10042. /// <summary>
  10043. /// Returns true if this type is assignable to some instance of the given template.
  10044. /// </summary>
  10045. public virtual bool IsAssignableToInstanceOf(TypeNode targetTemplate, out TypeNodeList templateArguments)
  10046. {
  10047. templateArguments = null;
  10048. if(this == CoreSystemTypes.Void || targetTemplate == null)
  10049. return false;
  10050. if(targetTemplate == this.Template)
  10051. {
  10052. templateArguments = this.TemplateArguments;
  10053. return true;
  10054. }
  10055. if(this != CoreSystemTypes.Object && this.BaseType != null && this.BaseType.IsAssignableToInstanceOf(targetTemplate, out templateArguments))
  10056. return true;
  10057. InterfaceList interfaces = this.Interfaces;
  10058. if(interfaces == null)
  10059. return false;
  10060. for(int i = 0, n = interfaces.Count; i < n; i++)
  10061. {
  10062. Interface iface = interfaces[i];
  10063. if(iface == null)
  10064. continue;
  10065. if(iface.IsAssignableToInstanceOf(targetTemplate, out templateArguments))
  10066. return true;
  10067. }
  10068. return false;
  10069. }
  10070. /// <summary>
  10071. /// Returns true if otherType is the base class of this type or if the base class of this type is derived from otherType.
  10072. /// </summary>
  10073. public virtual bool IsDerivedFrom(TypeNode otherType)
  10074. {
  10075. if(otherType == null)
  10076. return false;
  10077. TypeNode baseType = this.BaseType;
  10078. while(baseType != null)
  10079. {
  10080. if(baseType == otherType)
  10081. return true;
  10082. baseType = baseType.BaseType;
  10083. }
  10084. return false;
  10085. }
  10086. // Not thread safe code...
  10087. bool isCheckingInheritedFrom = false;
  10088. public virtual bool IsInheritedFrom(TypeNode otherType)
  10089. {
  10090. if(otherType == null)
  10091. return false;
  10092. if(this == otherType)
  10093. return true;
  10094. bool result = false;
  10095. if(this.isCheckingInheritedFrom)
  10096. goto done;
  10097. this.isCheckingInheritedFrom = true;
  10098. if(this.Template != null)
  10099. {
  10100. result = this.Template.IsInheritedFrom(otherType);
  10101. goto done;
  10102. }
  10103. if(otherType.Template != null)
  10104. {
  10105. otherType = otherType.Template;
  10106. }
  10107. TypeNode baseType = this.BaseType;
  10108. if(baseType != null && baseType.IsInheritedFrom(otherType))
  10109. {
  10110. result = true;
  10111. goto done;
  10112. }
  10113. InterfaceList interfaces = this.Interfaces;
  10114. if(interfaces == null)
  10115. goto done;
  10116. for(int i = 0, n = interfaces.Count; i < n; i++)
  10117. {
  10118. Interface iface = interfaces[i];
  10119. if(iface == null)
  10120. continue;
  10121. if(iface.IsInheritedFrom(otherType))
  10122. {
  10123. result = true;
  10124. goto done;
  10125. }
  10126. }
  10127. done:
  10128. this.isCheckingInheritedFrom = false;
  10129. return result;
  10130. }
  10131. public virtual bool IsStructurallyEquivalentTo(TypeNode type)
  10132. {
  10133. if(null == (object)type)
  10134. return false;
  10135. if(this == type)
  10136. return true;
  10137. if(this.Template == (object)null || type.Template == (object)null)
  10138. {
  10139. if(((object)this) == (object)type.Template || ((object)this.Template) == (object)type)
  10140. return true;
  10141. Identifier thisName = this.Template == null ? this.Name : this.Template.Name;
  10142. Identifier typeName = type.Template == null ? type.Name : type.Template.Name;
  10143. if(thisName == null || typeName == null || thisName.UniqueIdKey != typeName.UniqueIdKey)
  10144. return false;
  10145. if(this.NodeType != type.NodeType)
  10146. return false;
  10147. if(this.DeclaringType == null || type.DeclaringType == null)
  10148. return false;
  10149. }
  10150. if(this.TemplateArguments == null || type.TemplateArguments == null)
  10151. {
  10152. if(this.DeclaringType != null && (this.TemplateArguments == null || this.TemplateArguments.Count == 0) &&
  10153. (type.TemplateArguments == null || type.TemplateArguments.Count == 0))
  10154. return this.DeclaringType.IsStructurallyEquivalentTo(type.DeclaringType);
  10155. return false;
  10156. }
  10157. int n = this.TemplateArguments.Count;
  10158. if(n != type.TemplateArguments.Count)
  10159. return false;
  10160. if(this.Template != type.Template && !this.Template.IsStructurallyEquivalentTo(type.Template))
  10161. return false;
  10162. for(int i = 0; i < n; i++)
  10163. {
  10164. TypeNode ta1 = this.TemplateArguments[i];
  10165. TypeNode ta2 = type.TemplateArguments[i];
  10166. if(null == (object)ta1 || null == (object)ta2)
  10167. return false;
  10168. if(ta1 == ta2)
  10169. continue;
  10170. if(!ta1.IsStructurallyEquivalentTo(ta2))
  10171. return false;
  10172. }
  10173. if(this.DeclaringType != null)
  10174. return this.DeclaringType.IsStructurallyEquivalentTo(type.DeclaringType);
  10175. return true;
  10176. }
  10177. public virtual bool IsStructurallyEquivalentList(TypeNodeList list1, TypeNodeList list2)
  10178. {
  10179. if(list1 == null)
  10180. return list2 == null;
  10181. if(list2 == null)
  10182. return false;
  10183. int n = list1.Count;
  10184. if(list2.Count != n)
  10185. return false;
  10186. for(int i = 0; i < n; i++)
  10187. {
  10188. TypeNode t1 = list1[i];
  10189. TypeNode t2 = list2[i];
  10190. if(null == (object)t1 || null == (object)t2)
  10191. return false;
  10192. if(t1 == t2)
  10193. continue;
  10194. if(!t1.IsStructurallyEquivalentTo(t2))
  10195. return false;
  10196. }
  10197. return true;
  10198. }
  10199. public static TypeNode StripModifiers(TypeNode type)
  10200. //^ ensures t != null ==> result != null;
  10201. {
  10202. for(TypeModifier tmod = type as TypeModifier; tmod != null; tmod = type as TypeModifier)
  10203. type = tmod.ModifiedType;
  10204. // Don't strip under pointers or refs. We only strip top-level modifiers.
  10205. return type;
  10206. }
  10207. public static TypeNode DeepStripModifiers(TypeNode type)
  10208. //^ ensures type != null ==> result != null;
  10209. {
  10210. // strip off any outer type modifiers
  10211. for(TypeModifier tmod = type as TypeModifier; tmod != null; tmod = type as TypeModifier)
  10212. type = tmod.ModifiedType;
  10213. // For arrays and references, strip the inner type and then reconstruct the array or reference
  10214. ArrayType ar = type as ArrayType;
  10215. if(ar != null)
  10216. {
  10217. TypeNode t = TypeNode.DeepStripModifiers(ar.ElementType);
  10218. return t.GetArrayType(1);
  10219. }
  10220. Reference rt = type as Reference;
  10221. if(rt != null)
  10222. {
  10223. TypeNode t = TypeNode.DeepStripModifiers(rt.ElementType);
  10224. return t.GetReferenceType();
  10225. }
  10226. return type;
  10227. }
  10228. /// <summary>
  10229. /// Strip the given modifier from the type, modulo substructures that are instantiated with respect
  10230. /// to the given template type. In other words, traverse type and templateType in parallel, stripping common
  10231. /// non-null modifiers, but stop when reaching a type variable in the template type.
  10232. /// <param name="type">Type to be stripped</param>
  10233. /// <param name="modifiers">Modifiers to strip off</param>
  10234. /// <param name="templateType">Template bounding the stripping of type. Passing null for the templateType performs a full DeepStrip</param>
  10235. /// </summary>
  10236. public static TypeNode DeepStripModifiers(TypeNode type, TypeNode templateType, params TypeNode[] modifiers)
  10237. {
  10238. if(templateType == null)
  10239. return DeepStripModifiers(type, modifiers);
  10240. if(templateType is ITypeParameter)
  10241. return type;
  10242. // strip off inner modifiers then outer type modifier if it matches
  10243. OptionalModifier optmod = type as OptionalModifier;
  10244. if(optmod != null)
  10245. {
  10246. OptionalModifier optmodtemplate = (OptionalModifier)templateType; // must be in sync
  10247. TypeNode t = TypeNode.DeepStripModifiers(optmod.ModifiedType, optmodtemplate.ModifiedType, modifiers);
  10248. for(int i = 0; i < modifiers.Length; ++i)
  10249. {
  10250. if(optmod.Modifier == modifiers[i])
  10251. {
  10252. // strip it
  10253. return t;
  10254. }
  10255. }
  10256. return OptionalModifier.For(optmod.Modifier, t);
  10257. }
  10258. RequiredModifier reqmod = type as RequiredModifier;
  10259. if(reqmod != null)
  10260. {
  10261. RequiredModifier reqmodtemplate = (RequiredModifier)templateType; // must be in sync
  10262. TypeNode t = TypeNode.DeepStripModifiers(reqmod.ModifiedType, reqmodtemplate.ModifiedType, modifiers);
  10263. for(int i = 0; i < modifiers.Length; ++i)
  10264. {
  10265. if(reqmod.Modifier == modifiers[i])
  10266. {
  10267. // strip it
  10268. return t;
  10269. }
  10270. }
  10271. return RequiredModifier.For(reqmod.Modifier, t);
  10272. }
  10273. // For arrays and references, strip the inner type and then reconstruct the array or reference
  10274. ArrayType ar = type as ArrayType;
  10275. if(ar != null)
  10276. {
  10277. ArrayType artemplate = (ArrayType)templateType;
  10278. TypeNode t = TypeNode.DeepStripModifiers(ar.ElementType, artemplate.ElementType, modifiers);
  10279. return t.GetArrayType(1);
  10280. }
  10281. Reference rt = type as Reference;
  10282. if(rt != null)
  10283. {
  10284. Reference rttemplate = (Reference)templateType;
  10285. TypeNode t = TypeNode.DeepStripModifiers(rt.ElementType, rttemplate.ElementType, modifiers);
  10286. return t.GetReferenceType();
  10287. }
  10288. // strip template arguments
  10289. if(type.Template != null && type.TemplateArguments != null && type.TemplateArguments.Count > 0)
  10290. {
  10291. TypeNodeList strippedArgs = new TypeNodeList();
  10292. for(int i = 0; i < type.TemplateArguments.Count; i++)
  10293. {
  10294. //FIX: bug introduced by check in 16494
  10295. //templateType may have type parameters in either the TemplateArguments position or the templateParameters position.
  10296. //This may indicate an inconsistency in the template instantiation representation elsewhere.
  10297. TypeNodeList templateTypeArgs = templateType.TemplateArguments != null ? templateType.TemplateArguments : templateType.TemplateParameters;
  10298. strippedArgs.Add(DeepStripModifiers(type.TemplateArguments[i], templateTypeArgs[i], modifiers));
  10299. }
  10300. return type.Template.GetTemplateInstance(type, strippedArgs);
  10301. }
  10302. return type;
  10303. }
  10304. public static TypeNode DeepStripModifiers(TypeNode type, params TypeNode[] modifiers)
  10305. {
  10306. // strip off inner modifiers then outer type modifier if it matches
  10307. OptionalModifier optmod = type as OptionalModifier;
  10308. if(optmod != null)
  10309. {
  10310. TypeNode t = TypeNode.DeepStripModifiers(optmod.ModifiedType, modifiers);
  10311. for(int i = 0; i < modifiers.Length; ++i)
  10312. {
  10313. if(optmod.Modifier == modifiers[i])
  10314. {
  10315. // strip it
  10316. return t;
  10317. }
  10318. }
  10319. return OptionalModifier.For(optmod.Modifier, t);
  10320. }
  10321. RequiredModifier reqmod = type as RequiredModifier;
  10322. if(reqmod != null)
  10323. {
  10324. TypeNode t = TypeNode.DeepStripModifiers(reqmod.ModifiedType, modifiers);
  10325. for(int i = 0; i < modifiers.Length; ++i)
  10326. {
  10327. if(reqmod.Modifier == modifiers[i])
  10328. {
  10329. // strip it
  10330. return t;
  10331. }
  10332. }
  10333. return RequiredModifier.For(reqmod.Modifier, t);
  10334. }
  10335. // For arrays and references, strip the inner type and then reconstruct the array or reference
  10336. ArrayType ar = type as ArrayType;
  10337. if(ar != null)
  10338. {
  10339. TypeNode t = TypeNode.DeepStripModifiers(ar.ElementType, modifiers);
  10340. return t.GetArrayType(1);
  10341. }
  10342. Reference rt = type as Reference;
  10343. if(rt != null)
  10344. {
  10345. TypeNode t = TypeNode.DeepStripModifiers(rt.ElementType, modifiers);
  10346. return t.GetReferenceType();
  10347. }
  10348. // strip template arguments
  10349. if(type.Template != null && type.TemplateArguments != null && type.TemplateArguments.Count > 0)
  10350. {
  10351. TypeNodeList strippedArgs = new TypeNodeList();
  10352. for(int i = 0; i < type.TemplateArguments.Count; i++)
  10353. strippedArgs.Add(DeepStripModifiers(type.TemplateArguments[i], modifiers));
  10354. return type.Template.GetTemplateInstance(type, strippedArgs);
  10355. }
  10356. return type;
  10357. }
  10358. public static bool HasModifier(TypeNode type, TypeNode modifier)
  10359. {
  10360. // Don't look under pointers or refs.
  10361. TypeModifier tmod = type as TypeModifier;
  10362. if(tmod != null)
  10363. {
  10364. if(tmod.Modifier == modifier)
  10365. return true;
  10366. return TypeNode.HasModifier(tmod.ModifiedType, modifier);
  10367. }
  10368. return false;
  10369. }
  10370. public static TypeNode StripModifier(TypeNode type, TypeNode modifier)
  10371. {
  10372. // Don't strip under pointers or refs. We only strip top-level modifiers
  10373. TypeModifier tmod = type as TypeModifier;
  10374. if(tmod != null)
  10375. {
  10376. TypeNode et = TypeNode.StripModifier(tmod.ModifiedType, modifier);
  10377. //^ assert et != null;
  10378. if(tmod.Modifier == modifier)
  10379. return et;
  10380. if(et == tmod.ModifiedType)
  10381. return tmod;
  10382. if(tmod is OptionalModifier)
  10383. return OptionalModifier.For(tmod.Modifier, et);
  10384. return RequiredModifier.For(tmod.Modifier, et);
  10385. }
  10386. return type;
  10387. }
  10388. /// <summary>
  10389. /// Needed whenever we change the id of an existing member
  10390. /// </summary>
  10391. public virtual void ClearMemberTable()
  10392. {
  10393. lock(this)
  10394. {
  10395. this.memberTable = null;
  10396. this.memberCount = 0;
  10397. }
  10398. }
  10399. protected virtual void UpdateMemberTable(int range)
  10400. //^ ensures this.memberTable != null;
  10401. {
  10402. MemberList thisMembers = this.Members;
  10403. lock(this)
  10404. {
  10405. if(this.memberTable == null)
  10406. this.memberTable = new TrivialHashtable(32);
  10407. for(int i = this.memberCount; i < range; i++)
  10408. {
  10409. Member mem = thisMembers[i];
  10410. if(mem == null || mem.Name == null)
  10411. continue;
  10412. MemberList members = (MemberList)this.memberTable[mem.Name.UniqueIdKey];
  10413. if(members == null)
  10414. this.memberTable[mem.Name.UniqueIdKey] = members = new MemberList();
  10415. members.Add(mem);
  10416. }
  10417. this.memberCount = range;
  10418. this.constructors = null;
  10419. }
  10420. }
  10421. protected static MemberList WeedOutNonSpecialMethods(MemberList members, MethodFlags mask)
  10422. {
  10423. if(members == null)
  10424. return null;
  10425. bool membersOK = true;
  10426. for(int i = 0, n = members.Count; i < n; i++)
  10427. {
  10428. Method m = members[i] as Method;
  10429. if(m == null || (m.Flags & mask) == 0)
  10430. {
  10431. membersOK = false;
  10432. break;
  10433. }
  10434. }
  10435. if(membersOK)
  10436. return members;
  10437. MemberList newMembers = new MemberList();
  10438. for(int i = 0, n = members.Count; i < n; i++)
  10439. {
  10440. Method m = members[i] as Method;
  10441. if(m == null || (m.Flags & mask) == 0)
  10442. continue;
  10443. newMembers.Add(m);
  10444. }
  10445. return newMembers;
  10446. }
  10447. public override void WriteDocumentation(XmlTextWriter xwriter)
  10448. {
  10449. base.WriteDocumentation(xwriter);
  10450. MemberList members = this.Members;
  10451. for(int i = 0, n = members == null ? 0 : members.Count; i < n; i++)
  10452. {
  10453. Member mem = members[i];
  10454. if(mem == null)
  10455. continue;
  10456. mem.WriteDocumentation(xwriter);
  10457. }
  10458. }
  10459. public override string ToString()
  10460. {
  10461. return this.GetFullUnmangledNameWithTypeParameters();
  10462. }
  10463. }
  10464. public class Class : TypeNode
  10465. {
  10466. internal readonly static Class DoesNotExist = new Class();
  10467. internal readonly static Class Dummy = new Class();
  10468. internal Class baseClass;
  10469. public Class BaseClassExpression;
  10470. public bool IsAbstractSealedContainerForStatics;
  10471. public Class()
  10472. : base(NodeType.Class)
  10473. {
  10474. }
  10475. public Class(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  10476. : base(NodeType.Class, provideNestedTypes, provideAttributes, provideMembers, handle)
  10477. {
  10478. }
  10479. public Class(Module declaringModule, TypeNode declaringType, AttributeList attributes, TypeFlags flags,
  10480. Identifier Namespace, Identifier name, Class baseClass, InterfaceList interfaces, MemberList members)
  10481. : base(declaringModule, declaringType, attributes, flags, Namespace, name, interfaces, members, NodeType.Class)
  10482. {
  10483. this.baseClass = baseClass;
  10484. }
  10485. /// <summary>
  10486. /// The class from which this class has been derived. Null if this class is System.Object.
  10487. /// </summary>
  10488. public virtual Class BaseClass
  10489. {
  10490. get
  10491. {
  10492. return baseClass;
  10493. }
  10494. set
  10495. {
  10496. baseClass = value;
  10497. }
  10498. }
  10499. public override void GetAbstractMethods(MethodList/*!*/ result)
  10500. {
  10501. if(!this.IsAbstract)
  10502. return;
  10503. MethodList candidates = new MethodList();
  10504. if(this.BaseClass != null)
  10505. {
  10506. this.BaseClass.GetAbstractMethods(candidates);
  10507. for(int i = 0, n = candidates.Count; i < n; i++)
  10508. {
  10509. Method meth = candidates[i];
  10510. if(!this.ImplementsMethod(meth, false))
  10511. result.Add(meth);
  10512. }
  10513. }
  10514. //Add any abstract methods declared inside this class
  10515. MemberList members = this.Members;
  10516. for(int i = 0, n = members.Count; i < n; i++)
  10517. {
  10518. Method meth = members[i] as Method;
  10519. if(meth == null)
  10520. continue;
  10521. if(meth.IsAbstract)
  10522. result.Add(meth);
  10523. }
  10524. //For each interface, get abstract methods and keep those that are not implemented by this class or a base class
  10525. InterfaceList interfaces = this.Interfaces;
  10526. if(interfaces != null)
  10527. for(int i = 0, n = interfaces.Count; i < n; i++)
  10528. {
  10529. Interface iface = interfaces[i];
  10530. if(iface == null)
  10531. continue;
  10532. MemberList imembers = iface.Members;
  10533. if(imembers == null)
  10534. continue;
  10535. for(int j = 0, m = imembers.Count; j < m; j++)
  10536. {
  10537. Method meth = imembers[j] as Method;
  10538. if(meth == null)
  10539. continue;
  10540. if(this.ImplementsExplicitly(meth))
  10541. continue;
  10542. if(this.ImplementsMethod(meth, true))
  10543. continue;
  10544. if(this.AlreadyInList(result, meth))
  10545. continue;
  10546. result.Add(meth);
  10547. }
  10548. }
  10549. }
  10550. protected bool AlreadyInList(MethodList list, Method method)
  10551. {
  10552. if(list == null)
  10553. return false;
  10554. for(int i = 0, n = list.Count; i < n; i++)
  10555. {
  10556. if(list[i] == method)
  10557. return true;
  10558. }
  10559. return false;
  10560. }
  10561. }
  10562. public class ClosureClass : Class
  10563. {
  10564. public ClosureClass()
  10565. {
  10566. }
  10567. }
  10568. /// <summary>
  10569. /// 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.
  10570. /// </summary>
  10571. //TODO: use delegation rather than inheritance to achieve this
  10572. public class Scope : Class
  10573. {
  10574. public Scope()
  10575. {
  10576. }
  10577. public Scope(Scope outerScope)
  10578. {
  10579. this.OuterScope = outerScope;
  10580. }
  10581. protected Scope outerScope;
  10582. public SourceContext LexicalSourceExtent;
  10583. public Scope OuterScope
  10584. {
  10585. get
  10586. {
  10587. if(this.outerScope == null)
  10588. this.outerScope = (Scope)this.baseClass;
  10589. return this.outerScope;
  10590. }
  10591. set
  10592. {
  10593. this.baseClass = this.outerScope = value;
  10594. }
  10595. }
  10596. public virtual TypeNode GetType(Identifier typeName)
  10597. {
  10598. return this.GetNestedType(typeName);
  10599. }
  10600. }
  10601. public class TypeScope : Scope
  10602. {
  10603. public TypeNode Type;
  10604. public TypeScope() { }
  10605. public TypeScope(Scope parentScope, TypeNode/*!*/ type)
  10606. {
  10607. this.baseClass = parentScope;
  10608. this.DeclaringModule = type.DeclaringModule;
  10609. this.Type = type;
  10610. if(type != null && type.PartiallyDefines != null)
  10611. this.Type = type.PartiallyDefines;
  10612. this.templateParameters = type.TemplateParameters;
  10613. if(type != null)
  10614. this.LexicalSourceExtent = type.SourceContext;
  10615. }
  10616. public override MemberList/*!*/ GetMembersNamed(Identifier name)
  10617. {
  10618. TypeNode t = this.Type;
  10619. MemberList result = null;
  10620. while(t != null)
  10621. {
  10622. result = t.GetMembersNamed(name);
  10623. if(result.Count > 0)
  10624. return result;
  10625. t = t.BaseType;
  10626. }
  10627. if(result != null)
  10628. return result;
  10629. return new MemberList();
  10630. }
  10631. public override MemberList Members
  10632. {
  10633. get
  10634. {
  10635. return this.Type.Members;
  10636. }
  10637. set
  10638. {
  10639. base.Members = value;
  10640. }
  10641. }
  10642. }
  10643. public class MethodScope : Scope
  10644. {
  10645. protected Class closureClass;
  10646. public virtual Class ClosureClass
  10647. {
  10648. get
  10649. {
  10650. //if (this.DeclaringMethod == null) return null;
  10651. Class c = this.closureClass;
  10652. if(c == null)
  10653. {
  10654. c = this.closureClass = new ClosureClass();
  10655. c.Name = Identifier.For("closure:" + this.UniqueKey);
  10656. c.BaseClass = CoreSystemTypes.Object;
  10657. Class bclass = this.BaseClass;
  10658. c.DeclaringModule = bclass.DeclaringModule;
  10659. TypeScope tscope = bclass as TypeScope;
  10660. if(tscope != null)
  10661. c.DeclaringType = tscope.Type;
  10662. else
  10663. {
  10664. MethodScope mscope = bclass as MethodScope;
  10665. if(mscope != null)
  10666. c.DeclaringType = mscope.ClosureClass;
  10667. else
  10668. c.DeclaringType = ((BlockScope)bclass).ClosureClass;
  10669. }
  10670. c.IsGeneric = c.DeclaringType.IsGeneric || this.DeclaringMethod.IsGeneric;
  10671. c.TemplateParameters = this.CopyMethodTemplateParameters(c.DeclaringModule, c.DeclaringType);
  10672. c.Flags = TypeFlags.NestedPrivate | TypeFlags.SpecialName | TypeFlags.Sealed;
  10673. c.Interfaces = new InterfaceList();
  10674. if(this.ThisType != null)
  10675. {
  10676. Field f = new Field(c, null, FieldFlags.CompilerControlled | FieldFlags.SpecialName, StandardIds.ThisValue, this.ThisType, null);
  10677. this.ThisField = f;
  10678. c.Members.Add(f);
  10679. }
  10680. }
  10681. return c;
  10682. }
  10683. }
  10684. private TypeNodeList CopyMethodTemplateParameters(Module/*!*/ module, TypeNode/*!*/ type)
  10685. //^ requires this.DeclaringMethod != null;
  10686. {
  10687. TypeNodeList methTemplParams = this.DeclaringMethod.TemplateParameters;
  10688. if(methTemplParams == null || methTemplParams.Count == 0)
  10689. return null;
  10690. this.tpDup = new TemplateParameterDuplicator(module, type);
  10691. return this.tpDup.VisitTypeParameterList(methTemplParams);
  10692. }
  10693. private TemplateParameterDuplicator tpDup;
  10694. private class TemplateParameterDuplicator : Duplicator
  10695. {
  10696. public TemplateParameterDuplicator(Module/*!*/ module, TypeNode/*!*/ type)
  10697. : base(module, type)
  10698. {
  10699. }
  10700. public override TypeNode VisitTypeParameter(TypeNode typeParameter)
  10701. {
  10702. if(typeParameter == null)
  10703. return null;
  10704. TypeNode result = (TypeNode)this.DuplicateFor[typeParameter.UniqueKey];
  10705. if(result != null)
  10706. return result;
  10707. MethodTypeParameter mtp = typeParameter as MethodTypeParameter;
  10708. if(mtp != null)
  10709. {
  10710. TypeParameter tp = new TypeParameter();
  10711. this.DuplicateFor[typeParameter.UniqueKey] = tp;
  10712. tp.Name = mtp.Name;
  10713. tp.Interfaces = this.VisitInterfaceReferenceList(mtp.Interfaces);
  10714. tp.TypeParameterFlags = mtp.TypeParameterFlags;
  10715. tp.DeclaringModule = mtp.DeclaringModule;
  10716. tp.DeclaringMember = this.TargetType;
  10717. result = tp;
  10718. }
  10719. else
  10720. {
  10721. MethodClassParameter mcp = typeParameter as MethodClassParameter;
  10722. if(mcp != null)
  10723. {
  10724. ClassParameter cp = new ClassParameter();
  10725. this.DuplicateFor[typeParameter.UniqueKey] = cp;
  10726. cp.Name = mcp.Name;
  10727. cp.BaseClass = (Class)this.VisitTypeReference(mcp.BaseClass);
  10728. cp.Interfaces = this.VisitInterfaceReferenceList(mcp.Interfaces);
  10729. cp.TypeParameterFlags = mcp.TypeParameterFlags;
  10730. cp.DeclaringModule = mcp.DeclaringModule;
  10731. cp.DeclaringMember = this.TargetType;
  10732. result = cp;
  10733. }
  10734. }
  10735. if(result == null)
  10736. return typeParameter;
  10737. return result;
  10738. }
  10739. public override TypeNode VisitTypeReference(TypeNode type)
  10740. {
  10741. TypeNode result = base.VisitTypeReference(type);
  10742. if(result == type && (type is MethodClassParameter || type is MethodTypeParameter))
  10743. return this.VisitTypeParameter(type);
  10744. return result;
  10745. }
  10746. }
  10747. public virtual Class ClosureClassTemplateInstance
  10748. {
  10749. get
  10750. {
  10751. if(this.closureClassTemplateInstance == null)
  10752. {
  10753. if(this.DeclaringMethod == null || !this.DeclaringMethod.IsGeneric)
  10754. this.closureClassTemplateInstance = this.ClosureClass;
  10755. else
  10756. this.closureClassTemplateInstance = (Class)this.ClosureClass.GetTemplateInstance(this.DeclaringMethod.DeclaringType, this.DeclaringMethod.TemplateParameters);
  10757. }
  10758. return this.closureClassTemplateInstance;
  10759. }
  10760. }
  10761. Class closureClassTemplateInstance;
  10762. public TypeNode FixTypeReference(TypeNode type)
  10763. {
  10764. if(this.tpDup == null)
  10765. return type;
  10766. return this.tpDup.VisitTypeReference(type);
  10767. }
  10768. public virtual Boolean CapturedForClosure
  10769. {
  10770. get
  10771. {
  10772. return this.closureClass != null;
  10773. }
  10774. }
  10775. public UsedNamespaceList UsedNamespaces;
  10776. public Field ThisField;
  10777. public TypeNode ThisType;
  10778. public TypeNode ThisTypeInstance;
  10779. public Method DeclaringMethod;
  10780. public MethodScope() { }
  10781. public MethodScope(Class/*!*/ parentScope, UsedNamespaceList usedNamespaces)
  10782. : this(parentScope, usedNamespaces, null)
  10783. {
  10784. }
  10785. public MethodScope(Class/*!*/ parentScope, UsedNamespaceList usedNamespaces, Method method)
  10786. {
  10787. this.baseClass = parentScope;
  10788. this.UsedNamespaces = usedNamespaces;
  10789. this.DeclaringModule = parentScope.DeclaringModule;
  10790. this.DeclaringMethod = method;
  10791. if(method != null && (method.Flags & MethodFlags.Static) == 0)
  10792. this.ThisType = this.ThisTypeInstance = method.DeclaringType;
  10793. if(method != null)
  10794. this.LexicalSourceExtent = method.SourceContext;
  10795. }
  10796. }
  10797. public class BlockScope : Scope
  10798. {
  10799. public Block AssociatedBlock;
  10800. public bool MembersArePinned;
  10801. public virtual Class ClosureClass
  10802. {
  10803. get
  10804. {
  10805. BlockScope bscope = this.BaseClass as BlockScope;
  10806. if(bscope != null)
  10807. return bscope.ClosureClass;
  10808. MethodScope mscope = this.BaseClass as MethodScope;
  10809. if(mscope != null)
  10810. return mscope.ClosureClass;
  10811. return ((TypeScope)this.BaseClass).Type as Class;
  10812. }
  10813. }
  10814. public virtual Boolean CapturedForClosure
  10815. {
  10816. get
  10817. {
  10818. BlockScope bscope = this.BaseClass as BlockScope;
  10819. if(bscope != null)
  10820. return bscope.CapturedForClosure;
  10821. MethodScope mscope = this.BaseClass as MethodScope;
  10822. if(mscope != null)
  10823. return mscope.CapturedForClosure;
  10824. return false;
  10825. }
  10826. }
  10827. public BlockScope()
  10828. {
  10829. }
  10830. public BlockScope(Scope/*!*/ parentScope, Block associatedBlock)
  10831. {
  10832. this.AssociatedBlock = associatedBlock;
  10833. if(associatedBlock != null)
  10834. {
  10835. associatedBlock.HasLocals = true; //TODO: set only if there really are locals
  10836. associatedBlock.Scope = this;
  10837. }
  10838. this.baseClass = parentScope;
  10839. this.DeclaringModule = parentScope.DeclaringModule;
  10840. if(associatedBlock != null)
  10841. this.LexicalSourceExtent = associatedBlock.SourceContext;
  10842. }
  10843. }
  10844. public class AttributeScope : Scope
  10845. {
  10846. public AttributeNode AssociatedAttribute;
  10847. public AttributeScope(Scope parentScope, AttributeNode associatedAttribute)
  10848. {
  10849. this.AssociatedAttribute = associatedAttribute;
  10850. this.baseClass = parentScope;
  10851. if(associatedAttribute != null)
  10852. this.LexicalSourceExtent = associatedAttribute.SourceContext;
  10853. }
  10854. }
  10855. public class NamespaceScope : Scope
  10856. {
  10857. public Namespace AssociatedNamespace;
  10858. public Module AssociatedModule;
  10859. public TrivialHashtable AliasedType;
  10860. public TrivialHashtable AliasedNamespace;
  10861. protected TrivialHashtable/*!*/ aliasFor = new TrivialHashtable();
  10862. protected TrivialHashtable/*!*/ typeFor = new TrivialHashtable();
  10863. protected TrivialHashtable/*!*/ namespaceFor = new TrivialHashtable();
  10864. protected TrivialHashtable/*!*/ nestedNamespaceFullName = new TrivialHashtable();
  10865. protected readonly static AliasDefinition/*!*/ noSuchAlias = new AliasDefinition();
  10866. public NamespaceScope()
  10867. {
  10868. }
  10869. public NamespaceScope(Scope outerScope, Namespace associatedNamespace, Module associatedModule)
  10870. : base(outerScope)
  10871. {
  10872. //^ base;
  10873. this.AssociatedNamespace = associatedNamespace;
  10874. this.AssociatedModule = associatedModule;
  10875. this.DeclaringModule = associatedModule; //TODO: make this go away
  10876. if(associatedNamespace != null)
  10877. this.LexicalSourceExtent = associatedNamespace.SourceContext;
  10878. }
  10879. public virtual AliasDefinition GetAliasFor(Identifier name)
  10880. {
  10881. if(name == null || this.AssociatedNamespace == null || this.AssociatedModule == null || this.aliasFor == null)
  10882. {
  10883. Debug.Assert(false);
  10884. return null;
  10885. }
  10886. AliasDefinition alias = (AliasDefinition)this.aliasFor[name.UniqueIdKey];
  10887. if(alias == noSuchAlias)
  10888. return null;
  10889. if(alias != null)
  10890. return alias;
  10891. //Check if there is an alias with this uri
  10892. Scope scope = this;
  10893. while(scope != null)
  10894. {
  10895. NamespaceScope nsScope = scope as NamespaceScope;
  10896. if(nsScope != null && nsScope.AssociatedNamespace != null)
  10897. {
  10898. AliasDefinitionList aliases = nsScope.AssociatedNamespace.AliasDefinitions;
  10899. if(aliases != null)
  10900. for(int i = 0, n = aliases.Count; i < n; i++)
  10901. {
  10902. AliasDefinition aliasDef = aliases[i];
  10903. if(aliasDef == null || aliasDef.Alias == null)
  10904. continue;
  10905. if(aliasDef.Alias.UniqueIdKey == name.UniqueIdKey) { alias = aliasDef; goto done; }
  10906. }
  10907. }
  10908. scope = scope.OuterScope;
  10909. }
  10910. done:
  10911. if(alias != null)
  10912. this.aliasFor[name.UniqueIdKey] = alias;
  10913. else
  10914. this.aliasFor[name.UniqueIdKey] = noSuchAlias;
  10915. return alias;
  10916. }
  10917. public virtual AliasDefinition GetConflictingAlias(Identifier name)
  10918. {
  10919. if(name == null || this.typeFor == null || this.AssociatedNamespace == null || this.AssociatedModule == null)
  10920. {
  10921. Debug.Assert(false);
  10922. return null;
  10923. }
  10924. TypeNode type = this.AssociatedModule.GetType(this.AssociatedNamespace.FullNameId, name);
  10925. if(type != null)
  10926. {
  10927. AliasDefinitionList aliases = this.AssociatedNamespace.AliasDefinitions;
  10928. for(int i = 0, n = aliases == null ? 0 : aliases.Count; i < n; i++)
  10929. {
  10930. //^ assert aliases != null;
  10931. AliasDefinition aliasDef = aliases[i];
  10932. if(aliasDef == null || aliasDef.Alias == null)
  10933. continue;
  10934. if(aliasDef.Alias.UniqueIdKey == name.UniqueIdKey)
  10935. return aliasDef;
  10936. }
  10937. }
  10938. Scope scope = this;
  10939. while(scope != null)
  10940. {
  10941. NamespaceScope outerScope = scope.OuterScope as NamespaceScope;
  10942. if(outerScope != null)
  10943. return outerScope.GetConflictingAlias(name);
  10944. scope = scope.OuterScope;
  10945. }
  10946. return null;
  10947. }
  10948. public virtual Identifier GetUriFor(Identifier name)
  10949. {
  10950. AliasDefinition aliasDef = this.GetAliasFor(name);
  10951. if(aliasDef == null)
  10952. return null;
  10953. return aliasDef.AliasedUri;
  10954. }
  10955. public virtual Identifier GetNamespaceFullNameFor(Identifier name)
  10956. {
  10957. if(name == null || this.AssociatedNamespace == null || this.AssociatedModule == null || this.nestedNamespaceFullName == null)
  10958. {
  10959. Debug.Assert(false);
  10960. return null;
  10961. }
  10962. Identifier fullName = (Identifier)this.nestedNamespaceFullName[name.UniqueIdKey];
  10963. if(fullName == Identifier.Empty)
  10964. return null;
  10965. if(fullName != null)
  10966. return fullName;
  10967. //Check if there is an alias with this namespace
  10968. AliasDefinition aliasDef = this.GetAliasFor(name);
  10969. if(aliasDef != null && aliasDef.AliasedUri == null && aliasDef.AliasedType == null)
  10970. return aliasDef.AliasedExpression as Identifier;
  10971. //Check if module has a type with namespace equal to this namespace + name
  10972. fullName = name;
  10973. if(this.AssociatedNamespace.Name != null && this.AssociatedNamespace.Name.UniqueIdKey != Identifier.Empty.UniqueIdKey)
  10974. fullName = Identifier.For(this.AssociatedNamespace.FullName + "." + name);
  10975. if(this.AssociatedModule.IsValidNamespace(fullName))
  10976. {
  10977. this.namespaceFor[fullName.UniqueIdKey] = new TrivialHashtable();
  10978. goto returnFullName;
  10979. }
  10980. // If an inner type shadows an outer namespace, don't return the namespace
  10981. if(this.AssociatedModule.IsValidTypeName(this.AssociatedNamespace.Name, name)) { return null; }
  10982. AssemblyReferenceList arefs = this.AssociatedModule.AssemblyReferences;
  10983. for(int i = 0, n = arefs == null ? 0 : arefs.Count; i < n; i++)
  10984. {
  10985. AssemblyReference ar = arefs[i];
  10986. if(ar == null || ar.Assembly == null)
  10987. continue;
  10988. if(ar.Assembly.IsValidNamespace(fullName))
  10989. goto returnFullName;
  10990. // If an inner type shadows an outer namespace, don't return the namespace
  10991. if(ar.Assembly.IsValidTypeName(this.AssociatedNamespace.Name, name)) { return null; }
  10992. }
  10993. ModuleReferenceList mrefs = this.AssociatedModule.ModuleReferences;
  10994. if(mrefs != null)
  10995. for(int i = 0, n = mrefs.Count; i < n; i++)
  10996. {
  10997. ModuleReference mr = mrefs[i];
  10998. if(mr == null || mr.Module == null)
  10999. continue;
  11000. if(mr.Module.IsValidNamespace(fullName))
  11001. goto returnFullName;
  11002. // If an inner type shadows an outer namespace, don't return the namespace
  11003. if(mr.Module.IsValidTypeName(this.AssociatedNamespace.Name, name)) { return null; }
  11004. }
  11005. Scope scope = this.OuterScope;
  11006. while(scope != null && !(scope is NamespaceScope))
  11007. scope = scope.OuterScope;
  11008. if(scope != null)
  11009. return ((NamespaceScope)scope).GetNamespaceFullNameFor(name);
  11010. return null;
  11011. returnFullName:
  11012. this.nestedNamespaceFullName[name.UniqueIdKey] = fullName;
  11013. return fullName;
  11014. }
  11015. /// <summary>
  11016. /// Search this namespace for a type with this name nested in the given namespace. Also considers used name spaces.
  11017. /// If more than one type is found, a list is returned in duplicates.
  11018. /// </summary>
  11019. public virtual TypeNode GetType(Identifier Namespace, Identifier name, out TypeNodeList duplicates)
  11020. {
  11021. duplicates = null;
  11022. if(Namespace == null || name == null || this.AssociatedNamespace == null || this.AssociatedModule == null)
  11023. {
  11024. Debug.Assert(false);
  11025. return null;
  11026. }
  11027. if(this.namespaceFor == null)
  11028. {
  11029. Debug.Assert(false);
  11030. this.namespaceFor = new TrivialHashtable();
  11031. }
  11032. TrivialHashtable typeFor = (TrivialHashtable)this.namespaceFor[Namespace.UniqueIdKey];
  11033. if(typeFor == null)
  11034. this.namespaceFor[Namespace.UniqueIdKey] = typeFor = new TrivialHashtable();
  11035. TypeNode result = (TypeNode)typeFor[name.UniqueIdKey];
  11036. if(result == Class.DoesNotExist)
  11037. return null;
  11038. if(result != null)
  11039. return result;
  11040. //If the associated module declares a type with the given name in a nested namespace, it wins
  11041. Scope scope = this;
  11042. while(scope != null)
  11043. {
  11044. NamespaceScope nsScope = scope as NamespaceScope;
  11045. if(nsScope != null && nsScope.AssociatedNamespace != null)
  11046. {
  11047. Identifier nestedNamespace = Namespace;
  11048. if(nsScope.AssociatedNamespace.FullNameId != null && nsScope.AssociatedNamespace.FullNameId.UniqueIdKey != Identifier.Empty.UniqueIdKey)
  11049. nestedNamespace = Identifier.For(nsScope.AssociatedNamespace.FullName + "." + Namespace);
  11050. result = this.AssociatedModule.GetType(nestedNamespace, name);
  11051. if(result != null)
  11052. break;
  11053. }
  11054. scope = scope.OuterScope;
  11055. }
  11056. if(result == null)
  11057. {
  11058. //Now get into situations where there might be duplicates.
  11059. duplicates = new TypeNodeList();
  11060. //Check the used namespaces of this and outer namespace scopes
  11061. TrivialHashtable alreadyUsed = new TrivialHashtable();
  11062. scope = this;
  11063. while(scope != null)
  11064. {
  11065. NamespaceScope nsScope = scope as NamespaceScope;
  11066. if(nsScope != null && nsScope.AssociatedNamespace != null)
  11067. {
  11068. UsedNamespaceList usedNamespaces = nsScope.AssociatedNamespace.UsedNamespaces;
  11069. int n = usedNamespaces == null ? 0 : usedNamespaces.Count;
  11070. if(usedNamespaces != null)
  11071. for(int i = 0; i < n; i++)
  11072. {
  11073. UsedNamespace usedNs = usedNamespaces[i];
  11074. if(usedNs == null || usedNs.Namespace == null)
  11075. continue;
  11076. int key = usedNs.Namespace.UniqueIdKey;
  11077. if(alreadyUsed[key] != null)
  11078. continue;
  11079. alreadyUsed[key] = usedNs.Namespace;
  11080. Identifier usedNestedNamespace = Identifier.For(usedNs.Namespace + "." + Namespace);
  11081. result = this.AssociatedModule.GetType(usedNestedNamespace, name);
  11082. if(result != null)
  11083. duplicates.Add(result);
  11084. }
  11085. }
  11086. scope = scope.OuterScope;
  11087. }
  11088. if(duplicates.Count > 0)
  11089. result = duplicates[0];
  11090. }
  11091. if(result == null)
  11092. {
  11093. //The associated module does not have a type by this name, so check its referenced modules and assemblies
  11094. int numDups = 0;
  11095. //Check this namespace and outer namespaces
  11096. scope = this;
  11097. while(scope != null && result == null)
  11098. {
  11099. NamespaceScope nsScope = scope as NamespaceScope;
  11100. if(nsScope != null && nsScope.AssociatedNamespace != null)
  11101. {
  11102. Identifier nestedNamespace = Namespace;
  11103. if(nsScope.AssociatedNamespace.FullNameId != null && nsScope.AssociatedNamespace.FullNameId.UniqueIdKey != Identifier.Empty.UniqueIdKey)
  11104. nestedNamespace = Identifier.For(nsScope.AssociatedNamespace.FullName + "." + Namespace);
  11105. nsScope.GetReferencedTypes(nestedNamespace, name, duplicates);
  11106. numDups = duplicates.Count;
  11107. for(int i = numDups - 1; i >= 0; i--)
  11108. {
  11109. TypeNode dup = duplicates[i];
  11110. if(dup == null || !dup.IsPublic)
  11111. numDups--;
  11112. result = dup;
  11113. }
  11114. }
  11115. scope = scope.OuterScope;
  11116. }
  11117. if(numDups == 0)
  11118. {
  11119. if(duplicates.Count > 0)
  11120. duplicates = new TypeNodeList();
  11121. //Check the used namespaces of this and outer namespace scopes
  11122. TrivialHashtable alreadyUsed = new TrivialHashtable();
  11123. scope = this;
  11124. while(scope != null)
  11125. {
  11126. NamespaceScope nsScope = scope as NamespaceScope;
  11127. if(nsScope != null && nsScope.AssociatedNamespace != null)
  11128. {
  11129. UsedNamespaceList usedNamespaces = this.AssociatedNamespace.UsedNamespaces;
  11130. int n = usedNamespaces == null ? 0 : usedNamespaces.Count;
  11131. if(usedNamespaces != null)
  11132. for(int i = 0; i < n; i++)
  11133. {
  11134. UsedNamespace usedNs = usedNamespaces[i];
  11135. if(usedNs == null)
  11136. continue;
  11137. int key = usedNs.Namespace.UniqueIdKey;
  11138. if(alreadyUsed[key] != null)
  11139. continue;
  11140. alreadyUsed[key] = usedNs.Namespace;
  11141. Identifier usedNestedNamespace = Identifier.For(usedNs.Namespace + "." + Namespace);
  11142. this.GetReferencedTypes(usedNestedNamespace, name, duplicates);
  11143. }
  11144. }
  11145. scope = scope.OuterScope;
  11146. }
  11147. numDups = duplicates.Count;
  11148. for(int i = numDups - 1; i >= 0; i--)
  11149. {
  11150. TypeNode dup = duplicates[i];
  11151. if(dup == null || !dup.IsPublic)
  11152. numDups--;
  11153. result = dup;
  11154. }
  11155. }
  11156. if(numDups <= 1)
  11157. duplicates = null;
  11158. }
  11159. if(result == null)
  11160. typeFor[name.UniqueIdKey] = Class.DoesNotExist;
  11161. else
  11162. typeFor[name.UniqueIdKey] = result;
  11163. return result;
  11164. }
  11165. /// <summary>
  11166. /// Searches this namespace for a type with this name. Also considers aliases and used name spaces, including those of outer namespaces.
  11167. /// If more than one type is found, a list is returned in duplicates. Types defined in the associated
  11168. /// module mask types defined in referenced modules and assemblies. Results are cached and duplicates are returned only when
  11169. /// there is a cache miss.
  11170. /// </summary>
  11171. public virtual TypeNode GetType(Identifier name, out TypeNodeList duplicates)
  11172. {
  11173. return this.GetType(name, out duplicates, false);
  11174. }
  11175. public virtual TypeNode GetType(Identifier name, out TypeNodeList duplicates, bool returnNullIfHiddenByNestedNamespace)
  11176. {
  11177. duplicates = null;
  11178. if(name == null || this.typeFor == null || this.AssociatedNamespace == null || this.AssociatedModule == null)
  11179. {
  11180. Debug.Assert(false);
  11181. return null;
  11182. }
  11183. AssemblyNode associatedAssembly = this.AssociatedModule as AssemblyNode;
  11184. TypeNode result = (TypeNode)this.typeFor[name.UniqueIdKey];
  11185. if(result == Class.DoesNotExist)
  11186. return null;
  11187. if(result != null)
  11188. return result;
  11189. //If the associated module declares a type with the given name in this namespace, it wins
  11190. result = this.AssociatedModule.GetType(this.AssociatedNamespace.FullNameId, name);
  11191. if(result == null && returnNullIfHiddenByNestedNamespace)
  11192. {
  11193. //Do not proceed to outer namespaces or look at aliases. The nested namespace hides these.
  11194. Identifier fullName = name;
  11195. if(this.AssociatedNamespace.FullName != null && this.AssociatedNamespace.Name.UniqueIdKey != Identifier.Empty.UniqueIdKey)
  11196. fullName = Identifier.For(this.AssociatedNamespace.FullName + "." + name);
  11197. if(this.AssociatedModule.IsValidNamespace(fullName))
  11198. result = Class.DoesNotExist;
  11199. }
  11200. if(result == null)
  11201. {
  11202. //If the namespace (or an outer namespace) has an alias definition with this name it wins. (Expected to be mutually exclusive with above.)
  11203. Scope scope = this;
  11204. while(scope != null && result == null)
  11205. {
  11206. NamespaceScope nsScope = scope as NamespaceScope;
  11207. if(nsScope != null && nsScope.AliasedType != null)
  11208. result = (TypeNode)nsScope.AliasedType[name.UniqueIdKey];
  11209. if(result == null && returnNullIfHiddenByNestedNamespace && nsScope != null &&
  11210. nsScope.AliasedNamespace != null && nsScope.AliasedNamespace[name.UniqueIdKey] != null)
  11211. result = Class.DoesNotExist;
  11212. scope = scope.OuterScope;
  11213. }
  11214. }
  11215. if(result == null)
  11216. {
  11217. //Now get into situations where there might be duplicates.
  11218. duplicates = new TypeNodeList();
  11219. //Check the used namespaces of this and outer namespace scopes
  11220. TrivialHashtable alreadyUsed = new TrivialHashtable();
  11221. Scope scope = this;
  11222. while(scope != null)
  11223. {
  11224. NamespaceScope nsScope = scope as NamespaceScope;
  11225. if(nsScope != null && nsScope.AssociatedNamespace != null && nsScope.AssociatedModule != null)
  11226. {
  11227. UsedNamespaceList usedNamespaces = nsScope.AssociatedNamespace.UsedNamespaces;
  11228. int n = usedNamespaces == null ? 0 : usedNamespaces.Count;
  11229. if(usedNamespaces != null)
  11230. for(int i = 0; i < n; i++)
  11231. {
  11232. UsedNamespace usedNs = usedNamespaces[i];
  11233. if(usedNs == null || usedNs.Namespace == null)
  11234. continue;
  11235. int key = usedNs.Namespace.UniqueIdKey;
  11236. if(alreadyUsed[key] != null)
  11237. continue;
  11238. alreadyUsed[key] = usedNs.Namespace;
  11239. result = this.AssociatedModule.GetType(usedNs.Namespace, name);
  11240. //^ assert duplicates != null;
  11241. if(result != null)
  11242. duplicates.Add(result);
  11243. }
  11244. }
  11245. if(returnNullIfHiddenByNestedNamespace)
  11246. break;
  11247. scope = scope.OuterScope;
  11248. }
  11249. if(duplicates.Count > 0)
  11250. result = duplicates[0];
  11251. }
  11252. if(result == null)
  11253. //First see if the the current module has a class by this name in the empty namespace
  11254. result = this.AssociatedModule.GetType(Identifier.Empty, name);
  11255. if(result == null)
  11256. {
  11257. //The associated module does not have a type by this name, so check its referenced modules and assemblies
  11258. //First check this namespace
  11259. this.GetReferencedTypes(this.AssociatedNamespace.FullNameId, name, duplicates);
  11260. int numDups = duplicates.Count;
  11261. if(numDups == 1)
  11262. {
  11263. result = duplicates[0];
  11264. if(this.IsNotAccessible(associatedAssembly, result)) { numDups--; result = null; }
  11265. }
  11266. else
  11267. {
  11268. for(int i = numDups - 1; i >= 0; i--)
  11269. {
  11270. TypeNode dup = duplicates[i];
  11271. if(this.IsNotAccessible(associatedAssembly, dup)) { numDups--; continue; }
  11272. result = dup;
  11273. }
  11274. if(numDups == 0 && duplicates.Count > 0)
  11275. {
  11276. result = duplicates[0];
  11277. numDups = duplicates.Count;
  11278. }
  11279. }
  11280. if(numDups == 0)
  11281. {
  11282. if(duplicates.Count > 0)
  11283. duplicates = new TypeNodeList();
  11284. //Check the used namespaces of this and outer namespace scopes
  11285. TrivialHashtable alreadyUsed = new TrivialHashtable();
  11286. Scope scope = this;
  11287. while(scope != null)
  11288. {
  11289. NamespaceScope nsScope = scope as NamespaceScope;
  11290. if(nsScope != null)
  11291. {
  11292. UsedNamespaceList usedNamespaces = nsScope.AssociatedNamespace.UsedNamespaces;
  11293. int n = usedNamespaces == null ? 0 : usedNamespaces.Count;
  11294. if(usedNamespaces != null)
  11295. for(int i = 0; i < n; i++)
  11296. {
  11297. UsedNamespace usedNs = usedNamespaces[i];
  11298. if(usedNs == null || usedNs.Namespace == null)
  11299. continue;
  11300. int key = usedNs.Namespace.UniqueIdKey;
  11301. if(alreadyUsed[key] != null)
  11302. continue;
  11303. alreadyUsed[key] = usedNs.Namespace;
  11304. this.GetReferencedTypes(usedNs.Namespace, name, duplicates);
  11305. }
  11306. }
  11307. scope = scope.OuterScope;
  11308. if(returnNullIfHiddenByNestedNamespace)
  11309. break;
  11310. }
  11311. numDups = duplicates.Count;
  11312. for(int i = numDups - 1; i >= 0; i--)
  11313. {
  11314. TypeNode dup = duplicates[i];
  11315. if(this.IsNotAccessible(associatedAssembly, dup))
  11316. {
  11317. numDups--;
  11318. continue;
  11319. }
  11320. result = dup;
  11321. }
  11322. }
  11323. if(numDups == 0)
  11324. {
  11325. if(duplicates.Count > 0)
  11326. duplicates = new TypeNodeList();
  11327. this.GetReferencedTypes(Identifier.Empty, name, duplicates);
  11328. numDups = duplicates.Count;
  11329. for(int i = numDups - 1; i >= 0; i--)
  11330. {
  11331. TypeNode dup = duplicates[i];
  11332. if(this.IsNotAccessible(associatedAssembly, dup))
  11333. {
  11334. numDups--;
  11335. continue;
  11336. }
  11337. result = dup;
  11338. }
  11339. }
  11340. if(numDups <= 1)
  11341. duplicates = null;
  11342. }
  11343. if(result == null)
  11344. this.typeFor[name.UniqueIdKey] = Class.DoesNotExist;
  11345. else
  11346. this.typeFor[name.UniqueIdKey] = result;
  11347. if(result == Class.DoesNotExist)
  11348. return null;
  11349. if(duplicates != null && duplicates.Count > 1 && this.AssociatedNamespace != null && this.AssociatedNamespace.Name != null && this.AssociatedNamespace.Name.Name != null)
  11350. {
  11351. result = null;
  11352. for(int i = 0, n = duplicates.Count; i < n; i++)
  11353. {
  11354. TypeNode t = duplicates[i];
  11355. if(t == null || t.Namespace == null)
  11356. continue;
  11357. if(this.AssociatedNamespace.Name.Name.StartsWith(t.Namespace.Name))
  11358. {
  11359. if(result != null)
  11360. {
  11361. result = null;
  11362. break;
  11363. }
  11364. result = t;
  11365. }
  11366. }
  11367. if(result != null)
  11368. duplicates = null;
  11369. else
  11370. result = duplicates[0];
  11371. }
  11372. return result;
  11373. }
  11374. private bool IsNotAccessible(AssemblyNode associatedAssembly, TypeNode dup)
  11375. {
  11376. if(dup == null)
  11377. return false;
  11378. return !dup.IsPublic && (associatedAssembly == null ||
  11379. !associatedAssembly.MayAccessInternalTypesOf(dup.DeclaringModule as AssemblyNode)) && !this.AssociatedModule.ContainsModule(dup.DeclaringModule);
  11380. }
  11381. /// <summary>
  11382. /// Searches the module and assembly references of the associated module to find types
  11383. /// </summary>
  11384. public virtual void GetReferencedTypes(Identifier Namespace, Identifier name, TypeNodeList types)
  11385. {
  11386. if(Namespace == null || name == null || types == null || this.AssociatedModule == null) { Debug.Assert(false); return; }
  11387. AssemblyReferenceList arefs = this.AssociatedModule.AssemblyReferences;
  11388. for(int i = 0, n = arefs == null ? 0 : arefs.Count; i < n; i++)
  11389. {
  11390. AssemblyReference ar = arefs[i];
  11391. if(ar == null || ar.Assembly == null)
  11392. continue;
  11393. TypeNode t = ar.Assembly.GetType(Namespace, name);
  11394. if(t == null)
  11395. continue;
  11396. //TODO: deal with type forwarding
  11397. types.Add(t);
  11398. }
  11399. ModuleReferenceList mrefs = this.AssociatedModule.ModuleReferences;
  11400. if(mrefs != null)
  11401. for(int i = 0, n = mrefs.Count; i < n; i++)
  11402. {
  11403. ModuleReference mr = mrefs[i];
  11404. if(mr == null || mr.Module == null)
  11405. continue;
  11406. TypeNode t = mr.Module.GetType(Namespace, name);
  11407. if(t == null)
  11408. continue;
  11409. types.Add(t);
  11410. }
  11411. }
  11412. }
  11413. public class DelegateNode : TypeNode
  11414. {
  11415. internal static readonly DelegateNode/*!*/ Dummy = new DelegateNode();
  11416. protected ParameterList parameters;
  11417. public virtual ParameterList Parameters
  11418. {
  11419. get
  11420. {
  11421. ParameterList pList = this.parameters;
  11422. if(pList == null)
  11423. {
  11424. MemberList members = this.Members; //Evaluate for side effect
  11425. if(members != null)
  11426. members = null;
  11427. lock(this)
  11428. {
  11429. if(this.parameters != null)
  11430. return this.parameters;
  11431. MemberList invokers = this.GetMembersNamed(StandardIds.Invoke);
  11432. for(int i = 0, n = invokers.Count; i < n; i++)
  11433. {
  11434. Method m = invokers[i] as Method;
  11435. if(m == null)
  11436. continue;
  11437. this.parameters = pList = m.Parameters;
  11438. this.returnType = m.ReturnType;
  11439. break;
  11440. }
  11441. }
  11442. }
  11443. return pList;
  11444. }
  11445. set
  11446. {
  11447. this.parameters = value;
  11448. }
  11449. }
  11450. protected TypeNode returnType;
  11451. public virtual TypeNode ReturnType
  11452. {
  11453. get
  11454. {
  11455. TypeNode rt = this.returnType;
  11456. if(rt == null)
  11457. {
  11458. ParameterList pars = this.Parameters; //Evaluate for side effect
  11459. if(pars != null)
  11460. pars = null;
  11461. rt = this.returnType;
  11462. }
  11463. return rt;
  11464. }
  11465. set
  11466. {
  11467. this.returnType = value;
  11468. }
  11469. }
  11470. public TypeNode ReturnTypeExpression;
  11471. public DelegateNode()
  11472. : base(NodeType.DelegateNode)
  11473. {
  11474. }
  11475. public DelegateNode(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  11476. : base(NodeType.DelegateNode, provideNestedTypes, provideAttributes, provideMembers, handle)
  11477. {
  11478. }
  11479. public DelegateNode(Module declaringModule, TypeNode declaringType, AttributeList attributes, TypeFlags flags,
  11480. Identifier Namespace, Identifier name, TypeNode returnType, ParameterList parameters)
  11481. : base(declaringModule, declaringType, attributes, flags, Namespace, name, null, null, NodeType.DelegateNode)
  11482. {
  11483. this.parameters = parameters;
  11484. this.returnType = returnType;
  11485. }
  11486. private bool membersAlreadyProvided;
  11487. public virtual void ProvideMembers()
  11488. {
  11489. if(this.membersAlreadyProvided)
  11490. return;
  11491. this.membersAlreadyProvided = true;
  11492. this.memberCount = 0;
  11493. MemberList members = this.members = new MemberList();
  11494. //ctor
  11495. ParameterList parameters = new ParameterList();
  11496. parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.Object, CoreSystemTypes.Object, null, null));
  11497. parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.Method, CoreSystemTypes.IntPtr, null, null));
  11498. InstanceInitializer ctor = new InstanceInitializer(this, null, parameters, null);
  11499. ctor.Flags |= MethodFlags.Public | MethodFlags.HideBySig;
  11500. ctor.CallingConvention = CallingConventionFlags.HasThis;
  11501. ctor.ImplFlags = MethodImplFlags.Runtime;
  11502. members.Add(ctor);
  11503. //Invoke
  11504. Method invoke = new Method(this, null, StandardIds.Invoke, this.Parameters, this.ReturnType, null);
  11505. invoke.Flags = MethodFlags.Public | MethodFlags.HideBySig | MethodFlags.Virtual;
  11506. invoke.CallingConvention = CallingConventionFlags.HasThis;
  11507. invoke.ImplFlags = MethodImplFlags.Runtime;
  11508. members.Add(invoke);
  11509. //BeginInvoke
  11510. ParameterList dparams = this.parameters;
  11511. int n = dparams == null ? 0 : dparams.Count;
  11512. parameters = new ParameterList();
  11513. for(int i = 0; i < n; i++)
  11514. {
  11515. //^ assert dparams != null;
  11516. Parameter p = dparams[i];
  11517. if(p == null)
  11518. continue;
  11519. parameters.Add((Parameter)p.Clone());
  11520. }
  11521. parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.callback, SystemTypes.AsyncCallback, null, null));
  11522. parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.Object, CoreSystemTypes.Object, null, null));
  11523. Method beginInvoke = new Method(this, null, StandardIds.BeginInvoke, parameters, SystemTypes.IASyncResult, null);
  11524. beginInvoke.Flags = MethodFlags.Public | MethodFlags.HideBySig | MethodFlags.NewSlot | MethodFlags.Virtual;
  11525. beginInvoke.CallingConvention = CallingConventionFlags.HasThis;
  11526. beginInvoke.ImplFlags = MethodImplFlags.Runtime;
  11527. members.Add(beginInvoke);
  11528. //EndInvoke
  11529. parameters = new ParameterList();
  11530. for(int i = 0; i < n; i++)
  11531. {
  11532. Parameter p = dparams[i];
  11533. if(p == null || p.Type == null || !(p.Type is Reference))
  11534. continue;
  11535. parameters.Add((Parameter)p.Clone());
  11536. }
  11537. parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.result, SystemTypes.IASyncResult, null, null));
  11538. Method endInvoke = new Method(this, null, StandardIds.EndInvoke, parameters, this.ReturnType, null);
  11539. endInvoke.Flags = MethodFlags.Public | MethodFlags.HideBySig | MethodFlags.NewSlot | MethodFlags.Virtual;
  11540. endInvoke.CallingConvention = CallingConventionFlags.HasThis;
  11541. endInvoke.ImplFlags = MethodImplFlags.Runtime;
  11542. members.Add(endInvoke);
  11543. if(!this.IsGeneric)
  11544. {
  11545. TypeNodeList templPars = this.TemplateParameters;
  11546. for(int i = 0, m = templPars == null ? 0 : templPars.Count; i < m; i++)
  11547. {
  11548. //^ assert templPars != null;
  11549. TypeNode tpar = templPars[i];
  11550. if(tpar == null)
  11551. continue;
  11552. members.Add(tpar);
  11553. }
  11554. }
  11555. }
  11556. }
  11557. public class FunctionType : DelegateNode
  11558. {
  11559. private FunctionType(Identifier name, TypeNode returnType, ParameterList parameters)
  11560. {
  11561. this.Flags = TypeFlags.Public | TypeFlags.Sealed;
  11562. this.Namespace = StandardIds.StructuralTypes;
  11563. this.Name = name;
  11564. this.returnType = returnType;
  11565. this.parameters = parameters;
  11566. }
  11567. public static FunctionType For(TypeNode returnType, ParameterList parameters, TypeNode referringType)
  11568. {
  11569. if(returnType == null || referringType == null)
  11570. return null;
  11571. Module module = referringType.DeclaringModule;
  11572. if(module == null)
  11573. return null;
  11574. TypeFlags visibility = returnType.Flags & TypeFlags.VisibilityMask;
  11575. StringBuilder name = new StringBuilder();
  11576. name.Append("Function_");
  11577. name.Append(returnType.Name.ToString());
  11578. int n = parameters == null ? 0 : parameters.Count;
  11579. if(parameters != null)
  11580. for(int i = 0; i < n; i++)
  11581. {
  11582. Parameter p = parameters[i];
  11583. if(p == null || p.Type == null)
  11584. continue;
  11585. visibility = TypeNode.GetVisibilityIntersection(visibility, p.Type.Flags & TypeFlags.VisibilityMask);
  11586. name.Append('_');
  11587. name.Append(p.Type.Name.ToString());
  11588. }
  11589. FunctionType func = null;
  11590. int count = 0;
  11591. string fNameString = name.ToString();
  11592. Identifier fName = Identifier.For(fNameString);
  11593. TypeNode result = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, fName);
  11594. while(result != null)
  11595. {
  11596. //Mangled name is the same. But mangling is not unique (types are not qualified with assemblies), so check for equality.
  11597. func = result as FunctionType;
  11598. bool goodMatch = func != null && func.ReturnType == returnType;
  11599. if(goodMatch)
  11600. {
  11601. //^ assert func != null;
  11602. ParameterList fpars = func.Parameters;
  11603. int m = fpars == null ? 0 : fpars.Count;
  11604. goodMatch = n == m;
  11605. if(parameters != null && fpars != null)
  11606. for(int i = 0; i < n && goodMatch; i++)
  11607. {
  11608. Parameter p = parameters[i];
  11609. Parameter q = fpars[i];
  11610. goodMatch = p != null && q != null && p.Type == q.Type;
  11611. }
  11612. }
  11613. if(goodMatch)
  11614. return func;
  11615. //Mangle some more
  11616. fName = Identifier.For(fNameString + (++count).ToString());
  11617. result = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, fName);
  11618. }
  11619. if(parameters != null)
  11620. {
  11621. ParameterList clonedParams = new ParameterList();
  11622. for(int i = 0; i < n; i++)
  11623. {
  11624. Parameter p = parameters[i];
  11625. if(p != null)
  11626. p = (Parameter)p.Clone();
  11627. clonedParams.Add(p);
  11628. }
  11629. parameters = clonedParams;
  11630. }
  11631. func = new FunctionType(fName, returnType, parameters);
  11632. func.DeclaringModule = module;
  11633. switch(visibility)
  11634. {
  11635. case TypeFlags.NestedFamANDAssem:
  11636. case TypeFlags.NestedFamily:
  11637. case TypeFlags.NestedPrivate:
  11638. referringType.Members.Add(func);
  11639. func.DeclaringType = referringType;
  11640. func.Flags &= ~TypeFlags.VisibilityMask;
  11641. func.Flags |= TypeFlags.NestedPrivate;
  11642. break;
  11643. default:
  11644. module.Types.Add(func);
  11645. break;
  11646. }
  11647. module.StructurallyEquivalentType[func.Name.UniqueIdKey] = func;
  11648. func.ProvideMembers();
  11649. return func;
  11650. }
  11651. public override bool IsStructural
  11652. {
  11653. get { return true; }
  11654. }
  11655. protected TypeNodeList structuralElementTypes;
  11656. public override TypeNodeList StructuralElementTypes
  11657. {
  11658. get
  11659. {
  11660. TypeNodeList result = this.structuralElementTypes;
  11661. if(result != null)
  11662. return result;
  11663. this.structuralElementTypes = result = new TypeNodeList();
  11664. result.Add(this.ReturnType);
  11665. ParameterList pars = this.Parameters;
  11666. for(int i = 0, n = pars == null ? 0 : pars.Count; i < n; i++)
  11667. {
  11668. Parameter par = pars[i];
  11669. if(par == null || par.Type == null)
  11670. continue;
  11671. result.Add(par.Type);
  11672. }
  11673. return result;
  11674. }
  11675. }
  11676. public override bool IsStructurallyEquivalentTo(TypeNode type)
  11677. {
  11678. if(type == null)
  11679. return false;
  11680. if(this == type)
  11681. return true;
  11682. FunctionType t = type as FunctionType;
  11683. if(t == null)
  11684. return false;
  11685. if(this.Template != null)
  11686. return base.IsStructurallyEquivalentTo(t);
  11687. if(this.Flags != t.Flags)
  11688. return false;
  11689. if(this.ReturnType == null || t.ReturnType == null)
  11690. return false;
  11691. if(this.ReturnType != t.ReturnType && !this.ReturnType.IsStructurallyEquivalentTo(t.ReturnType))
  11692. return false;
  11693. if(this.Parameters == null)
  11694. return t.Parameters == null;
  11695. if(t.Parameters == null)
  11696. return false;
  11697. int n = this.Parameters.Count;
  11698. if(n != t.Parameters.Count)
  11699. return false;
  11700. for(int i = 0; i < n; i++)
  11701. {
  11702. Parameter p1 = this.Parameters[i];
  11703. Parameter p2 = t.Parameters[i];
  11704. if(p1 == null || p2 == null)
  11705. return false;
  11706. if(p1.Type == null || p2.Type == null)
  11707. return false;
  11708. if(p1.Type != p2.Type && !p1.Type.IsStructurallyEquivalentTo(p2.Type))
  11709. return false;
  11710. }
  11711. return true;
  11712. }
  11713. }
  11714. public class EnumNode : TypeNode
  11715. {
  11716. internal readonly static EnumNode/*!*/ Dummy = new EnumNode();
  11717. public EnumNode()
  11718. : base(NodeType.EnumNode)
  11719. {
  11720. this.typeCode = ElementType.ValueType;
  11721. this.Flags |= TypeFlags.Sealed;
  11722. }
  11723. public EnumNode(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  11724. : base(NodeType.EnumNode, provideNestedTypes, provideAttributes, provideMembers, handle)
  11725. {
  11726. this.typeCode = ElementType.ValueType;
  11727. this.Flags |= TypeFlags.Sealed;
  11728. }
  11729. public EnumNode(Module declaringModule, TypeNode declaringType, AttributeList attributes, TypeFlags typeAttributes,
  11730. Identifier Namespace, Identifier name, InterfaceList interfaces, MemberList members)
  11731. : base(declaringModule, declaringType, attributes, typeAttributes, Namespace, name, interfaces, members, NodeType.EnumNode)
  11732. {
  11733. this.typeCode = ElementType.ValueType;
  11734. this.Flags |= TypeFlags.Sealed;
  11735. }
  11736. public override bool IsUnmanaged
  11737. {
  11738. get
  11739. {
  11740. return true;
  11741. }
  11742. }
  11743. protected internal TypeNode underlyingType;
  11744. /// <summary>
  11745. /// The underlying integer type used to store values of this enumeration.
  11746. /// </summary>
  11747. public virtual TypeNode UnderlyingType
  11748. {
  11749. get
  11750. {
  11751. if(this.underlyingType == null)
  11752. {
  11753. if(this.template is EnumNode)
  11754. return this.underlyingType = ((EnumNode)this.template).UnderlyingType;
  11755. this.underlyingType = CoreSystemTypes.Int32;
  11756. MemberList members = this.Members;
  11757. for(int i = 0, n = members.Count; i < n; i++)
  11758. {
  11759. Member mem = members[i];
  11760. Field f = mem as Field;
  11761. if(f != null && (f.Flags & FieldFlags.Static) == 0)
  11762. return this.underlyingType = f.Type;
  11763. }
  11764. }
  11765. return this.underlyingType;
  11766. }
  11767. set
  11768. {
  11769. this.underlyingType = value;
  11770. MemberList members = this.Members;
  11771. for(int i = 0, n = members.Count; i < n; i++)
  11772. {
  11773. Member mem = members[i];
  11774. Field f = mem as Field;
  11775. if(f != null && (f.Flags & FieldFlags.Static) == 0)
  11776. {
  11777. f.Type = value;
  11778. return;
  11779. }
  11780. }
  11781. this.Members.Add(new Field(this, null, FieldFlags.Public | FieldFlags.SpecialName | FieldFlags.RTSpecialName, StandardIds.Value__, value, null));
  11782. }
  11783. }
  11784. public TypeNode UnderlyingTypeExpression;
  11785. }
  11786. public class Interface : TypeNode
  11787. {
  11788. protected TrivialHashtable jointMemberTable;
  11789. protected MemberList jointDefaultMembers;
  11790. internal static readonly Interface/*!*/ Dummy = new Interface();
  11791. public Interface()
  11792. : base(NodeType.Interface)
  11793. {
  11794. this.Flags = TypeFlags.Interface | TypeFlags.Abstract;
  11795. }
  11796. public Interface(InterfaceList baseInterfaces)
  11797. : base(NodeType.Interface)
  11798. {
  11799. this.Interfaces = baseInterfaces;
  11800. this.Flags = TypeFlags.Interface | TypeFlags.Abstract;
  11801. }
  11802. public Interface(InterfaceList baseInterfaces, NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  11803. : base(NodeType.Interface, provideNestedTypes, provideAttributes, provideMembers, handle)
  11804. {
  11805. this.Interfaces = baseInterfaces;
  11806. }
  11807. public Interface(Module declaringModule, TypeNode declaringType, AttributeList attributes, TypeFlags flags,
  11808. Identifier Namespace, Identifier name, InterfaceList baseInterfaces, MemberList members)
  11809. : base(declaringModule, declaringType, attributes, flags, Namespace, name, baseInterfaces, members, NodeType.Interface)
  11810. {
  11811. this.Flags |= TypeFlags.Interface | TypeFlags.Abstract;
  11812. }
  11813. public override void GetAbstractMethods(MethodList/*!*/ result)
  11814. {
  11815. MemberList members = this.Members;
  11816. if(members == null)
  11817. return;
  11818. for(int i = 0, n = members.Count; i < n; i++)
  11819. {
  11820. Method m = members[i] as Method;
  11821. if(m != null)
  11822. result.Add(m);
  11823. }
  11824. }
  11825. public virtual MemberList GetAllDefaultMembers()
  11826. {
  11827. if(this.jointDefaultMembers == null)
  11828. {
  11829. this.jointDefaultMembers = new MemberList();
  11830. MemberList defs = this.DefaultMembers;
  11831. for(int i = 0, n = defs == null ? 0 : defs.Count; i < n; i++)
  11832. this.jointDefaultMembers.Add(defs[i]);
  11833. InterfaceList interfaces = this.Interfaces;
  11834. if(interfaces != null)
  11835. for(int j = 0, m = interfaces.Count; j < m; j++)
  11836. {
  11837. Interface iface = interfaces[j];
  11838. if(iface == null)
  11839. continue;
  11840. defs = iface.GetAllDefaultMembers();
  11841. if(defs == null)
  11842. continue;
  11843. for(int i = 0, n = defs.Count; i < n; i++)
  11844. this.jointDefaultMembers.Add(defs[i]);
  11845. }
  11846. }
  11847. return this.jointDefaultMembers;
  11848. }
  11849. public virtual MemberList GetAllMembersNamed(Identifier/*!*/ name)
  11850. {
  11851. lock(this)
  11852. {
  11853. TrivialHashtable memberTable = this.jointMemberTable;
  11854. if(memberTable == null)
  11855. this.jointMemberTable = memberTable = new TrivialHashtable();
  11856. MemberList result = (MemberList)memberTable[name.UniqueIdKey];
  11857. if(result != null)
  11858. return result;
  11859. memberTable[name.UniqueIdKey] = result = new MemberList();
  11860. MemberList members = this.GetMembersNamed(name);
  11861. for(int i = 0, n = members == null ? 0 : members.Count; i < n; i++)
  11862. result.Add(members[i]);
  11863. InterfaceList interfaces = this.Interfaces;
  11864. for(int j = 0, m = interfaces == null ? 0 : interfaces.Count; j < m; j++)
  11865. {
  11866. Interface iface = interfaces[j];
  11867. if(iface == null)
  11868. continue;
  11869. members = iface.GetAllMembersNamed(name);
  11870. if(members != null)
  11871. for(int i = 0, n = members.Count; i < n; i++)
  11872. result.Add(members[i]);
  11873. }
  11874. members = CoreSystemTypes.Object.GetMembersNamed(name);
  11875. for(int i = 0, n = members == null ? 0 : members.Count; i < n; i++)
  11876. result.Add(members[i]);
  11877. return result;
  11878. }
  11879. }
  11880. }
  11881. public class Struct : TypeNode
  11882. {
  11883. internal static readonly Struct/*!*/ Dummy = new Struct();
  11884. public Struct()
  11885. : base(NodeType.Struct)
  11886. {
  11887. this.typeCode = ElementType.ValueType;
  11888. this.Flags = TypeFlags.Sealed;
  11889. }
  11890. public Struct(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  11891. : base(NodeType.Struct, provideNestedTypes, provideAttributes, provideMembers, handle)
  11892. {
  11893. this.typeCode = ElementType.ValueType;
  11894. }
  11895. public Struct(Module declaringModule, TypeNode declaringType, AttributeList attributes, TypeFlags flags,
  11896. Identifier Namespace, Identifier name, InterfaceList interfaces, MemberList members)
  11897. : base(declaringModule, declaringType, attributes, flags, Namespace, name, interfaces, members, NodeType.Struct)
  11898. {
  11899. this.Interfaces = interfaces;
  11900. this.typeCode = ElementType.ValueType;
  11901. this.Flags |= TypeFlags.Sealed;
  11902. }
  11903. protected bool cachedUnmanaged;
  11904. protected bool cachedUnmanagedIsValid;
  11905. /// <summary>True if the type is a value type containing only fields of unmanaged types.</summary>
  11906. public override bool IsUnmanaged
  11907. {
  11908. get
  11909. {
  11910. if(this.cachedUnmanagedIsValid)
  11911. return this.cachedUnmanaged;
  11912. this.cachedUnmanagedIsValid = true; //protect against cycles
  11913. this.cachedUnmanaged = true; //Self references should not influence the answer
  11914. if(this.IsPrimitive)
  11915. return this.cachedUnmanaged = true;
  11916. MemberList members = this.Members;
  11917. bool isUnmanaged = true;
  11918. for(int i = 0, n = members == null ? 0 : members.Count; i < n; i++)
  11919. {
  11920. Field f = members[i] as Field;
  11921. if(f == null || f.Type == null || f.IsStatic)
  11922. continue;
  11923. if(!f.Type.IsUnmanaged) { isUnmanaged = false; break; }
  11924. }
  11925. return this.cachedUnmanaged = isUnmanaged;
  11926. }
  11927. }
  11928. }
  11929. public interface ITypeParameter
  11930. {
  11931. Member DeclaringMember { get; set; }
  11932. /// <summary>
  11933. /// Zero based index into a parameter list containing this parameter.
  11934. /// </summary>
  11935. int ParameterListIndex { get; set; }
  11936. TypeParameterFlags TypeParameterFlags { get; set; }
  11937. bool IsUnmanaged { get; }
  11938. Identifier Name { get; }
  11939. Module DeclaringModule { get; }
  11940. TypeNode DeclaringType { get; }
  11941. SourceContext SourceContext { get; }
  11942. int UniqueKey { get; }
  11943. TypeFlags Flags { get; }
  11944. }
  11945. public class TypeParameter : Interface, ITypeParameter
  11946. {
  11947. public TypeParameter()
  11948. : base()
  11949. {
  11950. this.NodeType = NodeType.TypeParameter;
  11951. this.Flags = TypeFlags.Interface | TypeFlags.NestedPublic | TypeFlags.Abstract;
  11952. this.Namespace = StandardIds.TypeParameter;
  11953. }
  11954. public TypeParameter(InterfaceList baseInterfaces, NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  11955. : base(baseInterfaces, provideNestedTypes, provideAttributes, provideMembers, handle)
  11956. {
  11957. this.NodeType = NodeType.TypeParameter;
  11958. this.Flags = TypeFlags.Interface | TypeFlags.NestedPublic | TypeFlags.Abstract;
  11959. this.Namespace = StandardIds.TypeParameter;
  11960. }
  11961. public Member DeclaringMember
  11962. {
  11963. get { return this.declaringMember; }
  11964. set { this.declaringMember = value; }
  11965. }
  11966. private Member declaringMember;
  11967. public override Type GetRuntimeType()
  11968. {
  11969. TypeNode t = this.DeclaringMember as TypeNode;
  11970. if(t == null)
  11971. return null;
  11972. Type rt = t.GetRuntimeType();
  11973. if(rt == null)
  11974. return null;
  11975. System.Type[] typeParameters = rt.GetGenericArguments();
  11976. if(this.ParameterListIndex >= typeParameters.Length)
  11977. return null;
  11978. return typeParameters[this.ParameterListIndex];
  11979. }
  11980. /// <summary>
  11981. /// Zero based index into a parameter list containing this parameter.
  11982. /// </summary>
  11983. public int ParameterListIndex
  11984. {
  11985. get { return this.parameterListIndex; }
  11986. set { this.parameterListIndex = value; }
  11987. }
  11988. private int parameterListIndex;
  11989. public TypeParameterFlags TypeParameterFlags
  11990. {
  11991. get
  11992. {
  11993. return this.typeParameterFlags;
  11994. }
  11995. set
  11996. {
  11997. this.typeParameterFlags = value;
  11998. }
  11999. }
  12000. private TypeParameterFlags typeParameterFlags;
  12001. public override bool IsStructural
  12002. {
  12003. get { return true; }
  12004. }
  12005. /// <summary>True if the type serves as a parameter to a type template.</summary>
  12006. public override bool IsTemplateParameter
  12007. {
  12008. get
  12009. {
  12010. return true;
  12011. }
  12012. }
  12013. public override bool IsValueType
  12014. {
  12015. get
  12016. {
  12017. return ((this.TypeParameterFlags & TypeParameterFlags.ValueTypeConstraint) == TypeParameterFlags.ValueTypeConstraint);
  12018. }
  12019. }
  12020. public override XmlNode Documentation
  12021. {
  12022. get
  12023. {
  12024. if(this.documentation == null && this.declaringMember != null && this.Name != null)
  12025. {
  12026. XmlNode parentDoc = this.declaringMember.Documentation;
  12027. if(parentDoc != null && parentDoc.HasChildNodes)
  12028. {
  12029. string myName = this.Name.Name;
  12030. foreach(XmlNode child in parentDoc.ChildNodes)
  12031. {
  12032. if(child.Name == "typeparam" && child.Attributes != null)
  12033. {
  12034. foreach(XmlAttribute attr in child.Attributes)
  12035. {
  12036. if(attr != null && attr.Name == "name" && attr.Value == myName)
  12037. return this.documentation = child;
  12038. }
  12039. }
  12040. }
  12041. }
  12042. }
  12043. return this.documentation;
  12044. }
  12045. set
  12046. {
  12047. this.documentation = value;
  12048. }
  12049. }
  12050. public override string HelpText
  12051. {
  12052. get
  12053. {
  12054. if(this.helpText == null)
  12055. {
  12056. XmlNode doc = this.Documentation;
  12057. if(doc != null)
  12058. this.helpText = doc.InnerText;
  12059. }
  12060. return this.helpText;
  12061. }
  12062. set
  12063. {
  12064. this.helpText = value;
  12065. }
  12066. }
  12067. protected internal TypeNodeList structuralElementTypes;
  12068. public override TypeNodeList StructuralElementTypes
  12069. {
  12070. get
  12071. {
  12072. TypeNodeList result = this.structuralElementTypes;
  12073. if(result != null)
  12074. return result;
  12075. this.structuralElementTypes = result = new TypeNodeList();
  12076. if(this.BaseType != null)
  12077. result.Add(this.BaseType);
  12078. InterfaceList interfaces = this.Interfaces;
  12079. for(int i = 0, n = interfaces == null ? 0 : interfaces.Count; i < n; i++)
  12080. {
  12081. Interface iface = interfaces[i];
  12082. if(iface == null)
  12083. continue;
  12084. result.Add(iface);
  12085. }
  12086. return result;
  12087. }
  12088. }
  12089. internal override void AppendDocumentIdMangledName(StringBuilder/*!*/ sb, TypeNodeList methodTypeParameters, TypeNodeList typeParameters)
  12090. {
  12091. if(TargetPlatform.GenericTypeNamesMangleChar != 0)
  12092. {
  12093. int n = methodTypeParameters == null ? 0 : methodTypeParameters.Count;
  12094. for(int i = 0; i < n; i++)
  12095. {
  12096. //^ assert methodTypeParameters != null;
  12097. TypeNode mpar = methodTypeParameter