/SpecSharp/System.Compiler/Nodes.cs

# · C# · 19990 lines · 18381 code · 238 blank · 1371 comment · 6439 complexity · b111ae665abe1b7131c5e7543d4a30e7 MD5 · raw file

  1. //-----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) Microsoft Corporation. All Rights Reserved.
  4. //
  5. //-----------------------------------------------------------------------------
  6. using System;
  7. using System.Collections;
  8. using System.Collections.Generic;
  9. using System.Globalization;
  10. using System.Collections.Specialized;
  11. #if FxCop
  12. using AssemblyReferenceList = Microsoft.Cci.AssemblyReferenceCollection;
  13. using AttributeList = Microsoft.Cci.AttributeNodeCollection;
  14. using BlockList = Microsoft.Cci.BlockCollection;
  15. using ExpressionList = Microsoft.Cci.ExpressionCollection;
  16. using InstructionList = Microsoft.Cci.InstructionCollection;
  17. using Int32List = System.Collections.Generic.List<int>;
  18. using InterfaceList = Microsoft.Cci.InterfaceCollection;
  19. using MemberList = Microsoft.Cci.MemberCollection;
  20. using MethodList = Microsoft.Cci.MethodCollection;
  21. using ModuleReferenceList = Microsoft.Cci.ModuleReferenceCollection;
  22. using NamespaceList = Microsoft.Cci.NamespaceCollection;
  23. using ParameterList = Microsoft.Cci.ParameterCollection;
  24. using ResourceList = Microsoft.Cci.ResourceCollection;
  25. using SecurityAttributeList = Microsoft.Cci.SecurityAttributeCollection;
  26. using StatementList = Microsoft.Cci.StatementCollection;
  27. using TypeNodeList = Microsoft.Cci.TypeNodeCollection;
  28. using Win32ResourceList = Microsoft.Cci.Win32ResourceCollection;
  29. using Module = Microsoft.Cci.ModuleNode;
  30. using Class = Microsoft.Cci.ClassNode;
  31. using Interface = Microsoft.Cci.InterfaceNode;
  32. using Property = Microsoft.Cci.PropertyNode;
  33. using Event = Microsoft.Cci.EventNode;
  34. using Return = Microsoft.Cci.ReturnNode;
  35. using Throw = Microsoft.Cci.ThrowNode;
  36. #endif
  37. #if UseSingularityPDB
  38. using Microsoft.Singularity.PdbInfo;
  39. #endif
  40. #if CCINamespace
  41. using Cci = Microsoft.Cci;
  42. using Microsoft.Cci.Metadata;
  43. using Metadata = Microsoft.Cci.Metadata;
  44. #else
  45. using Cci = System.Compiler;
  46. using System.Compiler.Metadata;
  47. using Metadata = System.Compiler.Metadata;
  48. #endif
  49. using System.Diagnostics;
  50. using System.IO;
  51. using System.Text;
  52. #if !NoXml
  53. using System.Xml;
  54. #endif
  55. using BindingFlags = System.Reflection.BindingFlags;
  56. #if CCINamespace
  57. namespace Microsoft.Cci{
  58. #else
  59. namespace System.Compiler{
  60. #endif
  61. #if !FxCop
  62. /// <summary>
  63. /// This interface can be used to link an arbitrary source text provider into an IR tree via a DocumentText instance.
  64. /// </summary>
  65. public interface ISourceText{
  66. /// <summary>
  67. /// The number of characters in the source text.
  68. /// A "character" corresponds to a System.Char which is actually a Unicode UTF16 code point to be precise.
  69. /// </summary>
  70. int Length{get;}
  71. /// <summary>
  72. /// Retrieves a substring from this instance. The substring starts with the character at the specified index and has a specified length.
  73. /// </summary>
  74. string Substring(int startIndex, int length);
  75. /// <summary>
  76. /// Retrieves the character at the given position. The first character is at position zero.
  77. /// </summary>
  78. char this[int position]{get;}
  79. /// <summary>
  80. /// Indicates that the text has been fully scanned and futher references to the text are expected to be infrequent.
  81. /// The underlying object can now choose to clear cached information if it comes under resource pressure.
  82. /// </summary>
  83. void MakeCollectible();
  84. }
  85. public unsafe interface ISourceTextBuffer : ISourceText{
  86. /// <summary>
  87. /// Returns null unless the implementer is based on an ASCII buffer that stays alive as long at the implementer itself.
  88. /// An implementer that returns a non-null value is merely a wrapper to keep the buffer alive. No further methods will
  89. /// be called on the interface in this case.
  90. /// </summary>
  91. byte* Buffer{get;}
  92. }
  93. #endif
  94. #if !MinimalReader
  95. /// <summary>
  96. /// Use this after a source text has already been scanned and parsed. This allows the source text to get released
  97. /// if there is memory pressure, while still allowing portions of it to be retrieved on demand. This is useful when
  98. /// a large number of source files are read in, but only infrequent references are made to them.
  99. /// </summary>
  100. public sealed class CollectibleSourceText : ISourceText{
  101. private string/*!*/ filePath;
  102. private WeakReference/*!*/ fileContent;
  103. private int length;
  104. public CollectibleSourceText(string/*!*/ filePath, int length) {
  105. this.filePath = filePath;
  106. this.fileContent = new WeakReference(null);
  107. this.length = length;
  108. //^ base();
  109. }
  110. public CollectibleSourceText(string/*!*/ filePath, string fileContent) {
  111. this.filePath = filePath;
  112. this.fileContent = new WeakReference(fileContent);
  113. this.length = fileContent == null ? 0 : fileContent.Length;
  114. //^ base();
  115. }
  116. private string/*!*/ ReadFile() {
  117. string content = string.Empty;
  118. try {
  119. StreamReader sr = new StreamReader(filePath);
  120. content = sr.ReadToEnd();
  121. this.length = content.Length;
  122. sr.Close();
  123. }catch{}
  124. return content;
  125. }
  126. public string/*!*/ GetSourceText() {
  127. string source = (string)this.fileContent.Target;
  128. if (source != null) return source;
  129. source = this.ReadFile();
  130. this.fileContent.Target = source;
  131. return source;
  132. }
  133. int ISourceText.Length{get{return this.length;}}
  134. string ISourceText.Substring(int startIndex, int length){
  135. return this.GetSourceText().Substring(startIndex, length);
  136. }
  137. char ISourceText.this[int index]{
  138. get{
  139. return this.GetSourceText()[index];
  140. }
  141. }
  142. void ISourceText.MakeCollectible(){
  143. this.fileContent.Target = null;
  144. }
  145. }
  146. /// <summary>
  147. /// This class is used to wrap the string contents of a source file with an ISourceText interface. It is used while compiling
  148. /// a project the first time in order to obtain a symbol table. After that the StringSourceText instance is typically replaced with
  149. /// a CollectibleSourceText instance, so that the actual source text string can be collected. When a file is edited,
  150. /// and the editor does not provide its own ISourceText wrapper for its edit buffer, this class can be used to wrap a copy of the edit buffer.
  151. /// </summary>
  152. public sealed class StringSourceText : ISourceText{
  153. /// <summary>
  154. /// The wrapped string used to implement ISourceText. Use this value when unwrapping.
  155. /// </summary>
  156. public readonly string/*!*/ SourceText;
  157. /// <summary>
  158. /// True when the wrapped string is the contents of a file. Typically used to check if it safe to replace this
  159. /// StringSourceText instance with a CollectibleSourceText instance.
  160. /// </summary>
  161. public bool IsSameAsFileContents;
  162. public StringSourceText(string/*!*/ sourceText, bool isSameAsFileContents) {
  163. this.SourceText = sourceText;
  164. this.IsSameAsFileContents = isSameAsFileContents;
  165. //^ base();
  166. }
  167. int ISourceText.Length{get{return this.SourceText.Length;}}
  168. string ISourceText.Substring(int startIndex, int length){
  169. return this.SourceText.Substring(startIndex, length);
  170. }
  171. char ISourceText.this[int index]{
  172. get{
  173. return this.SourceText[index];
  174. }
  175. }
  176. void ISourceText.MakeCollectible(){
  177. }
  178. }
  179. #endif
  180. #if !FxCop
  181. /// <summary>
  182. /// This class provides a uniform interface to program sources provided in the form of Unicode strings,
  183. /// unsafe pointers to ascii buffers (as obtained from a memory mapped file, for instance) as well as
  184. /// arbitrary source text providers that implement the ISourceText interface.
  185. /// </summary>
  186. public sealed unsafe class DocumentText{
  187. /// <summary>
  188. /// If this is not null it is used to obtain 8-bit ASCII characters.
  189. /// </summary>
  190. public byte* AsciiStringPtr;
  191. /// <summary>
  192. /// If this is not null it represents a Unicode string encoded as UTF16.
  193. /// </summary>
  194. public string Source;
  195. /// <summary>
  196. /// If this is not null the object implement ISourceText provides some way to get at individual characters and substrings.
  197. /// </summary>
  198. public ISourceText TextProvider;
  199. /// <summary>
  200. /// The number of characters in the source document.
  201. /// A "character" corresponds to a System.Char which is actually a Unicode UTF16 code point to be precise.
  202. /// </summary>
  203. public int Length;
  204. public DocumentText(string source){
  205. if (source == null){Debug.Assert(false); return;}
  206. this.Source = source;
  207. this.Length = source.Length;
  208. }
  209. public DocumentText(ISourceText textProvider){
  210. if (textProvider == null){Debug.Assert(false); return;}
  211. this.TextProvider = textProvider;
  212. this.Length = textProvider.Length;
  213. }
  214. public unsafe DocumentText(ISourceTextBuffer textProvider){
  215. if (textProvider == null){Debug.Assert(false); return;}
  216. this.TextProvider = textProvider;
  217. this.AsciiStringPtr = textProvider.Buffer;
  218. this.Length = textProvider.Length;
  219. }
  220. /// <summary>
  221. /// Compare this.Substring(offset, length) for equality with str.
  222. /// Call this only if str.Length is known to be equal to length.
  223. /// </summary>
  224. public bool Equals(string str, int position, int length){ //TODO: (int position, int length, string str)
  225. if (str == null){Debug.Assert(false); return false;}
  226. if (str.Length != length){Debug.Assert(false); return false;}
  227. if (position < 0 || position+length > this.Length){Debug.Assert(false); return false;}
  228. unsafe{
  229. byte* p = this.AsciiStringPtr;
  230. if (p != null){
  231. for (int i = position, j = 0; j < length; i++, j++)
  232. if (((char)*(p+i)) != str[j]) return false;
  233. return true;
  234. }
  235. }
  236. string source = this.Source;
  237. if (source != null){
  238. for (int i = position, j = 0; j < length; i++, j++)
  239. if (source[i] != str[j]) return false;
  240. return true;
  241. }
  242. ISourceText myProvider = this.TextProvider;
  243. if (myProvider == null){Debug.Assert(false); return false;}
  244. for (int i = position, j = 0; j < length; i++, j++)
  245. if (myProvider[i] != str[j]) return false;
  246. return true;
  247. }
  248. /// <summary>
  249. /// Compares the substring of the specificied length starting at offset, with the substring in DocumentText starting at textOffset.
  250. /// </summary>
  251. /// <param name="offset">The index of the first character of the substring of this DocumentText.</param>
  252. /// <param name="text">The Document text with the substring being compared to.</param>
  253. /// <param name="textOffset">The index of the first character of the substring of the DocumentText being compared to.</param>
  254. /// <param name="length">The number of characters in the substring being compared.</param>
  255. /// <returns></returns>
  256. public bool Equals(int offset, DocumentText text, int textOffset, int length){ //TODO: (int position, int length, DocumentText text, int textPosition)
  257. if (offset < 0 || length < 0 || offset+length > this.Length){ Debug.Assert(false); return false;}
  258. if (textOffset < 0 || text == null || textOffset+length > text.Length){Debug.Assert(false); return false;}
  259. unsafe{
  260. byte* p = this.AsciiStringPtr;
  261. if (p != null){
  262. unsafe{
  263. byte* q = text.AsciiStringPtr;
  264. if (q != null){
  265. for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
  266. if (*(p+i) != *(q+j)) return false;
  267. return true;
  268. }
  269. }
  270. string textSource = text.Source;
  271. if (textSource != null){
  272. for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
  273. if (((char)*(p+i)) != textSource[j]) return false;
  274. return true;
  275. }
  276. ISourceText textProvider = text.TextProvider;
  277. if (textProvider == null){Debug.Assert(false); return false;}
  278. for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
  279. if (((char)*(p+i)) != textProvider[j]) return false;
  280. return true;
  281. }
  282. }
  283. string source = this.Source;
  284. if (source != null){
  285. unsafe{
  286. byte* q = text.AsciiStringPtr;
  287. if (q != null){
  288. for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
  289. if (source[i] != (char)*(q+j)) return false;
  290. return true;
  291. }
  292. }
  293. string textSource = text.Source;
  294. if (textSource != null){
  295. for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
  296. if (source[i] != textSource[j]) return false;
  297. return true;
  298. }
  299. ISourceText textProvider = text.TextProvider;
  300. if (textProvider == null){Debug.Assert(false); return false;}
  301. for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
  302. if (source[i] != textProvider[j]) return false;
  303. return true;
  304. }
  305. {
  306. ISourceText myProvider = this.TextProvider;
  307. if (myProvider == null){Debug.Assert(false); return false;}
  308. unsafe{
  309. byte* q = text.AsciiStringPtr;
  310. if (q != null){
  311. for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
  312. if (myProvider[i] != (char)*(q+j)) return false;
  313. return true;
  314. }
  315. }
  316. string textSource = text.Source;
  317. if (textSource != null){
  318. for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
  319. if (myProvider[i] != textSource[j]) return false;
  320. return true;
  321. }
  322. ISourceText textProvider = text.TextProvider;
  323. if (textProvider == null){Debug.Assert(false); return false;}
  324. for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
  325. if (myProvider[i] != textProvider[j]) return false;
  326. return true;
  327. }
  328. }
  329. /// <summary>
  330. /// Retrieves a substring from this instance. The substring starts at a specified character position and has a specified length.
  331. /// </summary>
  332. public string/*!*/ Substring(int position, int length){
  333. if (position < 0 || length < 0 || position+length > this.Length+1){Debug.Assert(false); return "";}
  334. if (position+length > this.Length) length = this.Length-position; //Allow virtual EOF character to be included in length
  335. if (this.AsciiStringPtr != null){
  336. unsafe{
  337. return new String((sbyte*)this.AsciiStringPtr, position, length, System.Text.Encoding.ASCII);
  338. }
  339. }else if (this.Source != null)
  340. return this.Source.Substring(position, length);
  341. else if (this.TextProvider != null)
  342. return this.TextProvider.Substring(position, length);
  343. else{
  344. Debug.Assert(false);
  345. return "";
  346. }
  347. }
  348. /// <summary>
  349. /// Retrieves the character at the given position. The first character is at position zero.
  350. /// </summary>
  351. public char this[int position]{
  352. get{
  353. if (position < 0 || position >= this.Length){Debug.Assert(false); return (char)0;}
  354. if (this.AsciiStringPtr != null){
  355. unsafe{
  356. unchecked{
  357. return (char) *(this.AsciiStringPtr+position);
  358. }
  359. }
  360. }else if (this.Source != null)
  361. return this.Source[position];
  362. else if (this.TextProvider != null)
  363. return this.TextProvider[position];
  364. else{
  365. Debug.Assert(false);
  366. return (char)0;
  367. }
  368. }
  369. }
  370. }
  371. /// <summary>
  372. /// A source document from which an Abstract Syntax Tree has been derived.
  373. /// </summary>
  374. public class Document{
  375. /// <summary>
  376. /// A Guid that identifies the kind of document to applications such as a debugger. Typically System.Diagnostics.SymbolStore.SymDocumentType.Text.
  377. /// </summary>
  378. public System.Guid DocumentType;
  379. /// <summary>
  380. /// A Guid that identifies the programming language used in the source document. Typically used by a debugger to locate language specific logic.
  381. /// </summary>
  382. public System.Guid Language;
  383. /// <summary>
  384. /// A Guid that identifies the compiler vendor programming language used in the source document. Typically used by a debugger to locate vendor specific logic.
  385. /// </summary>
  386. public System.Guid LanguageVendor;
  387. /// <summary>
  388. /// The line number corresponding to the first character in Text. Typically 1 but can be changed by C# preprocessor directives.
  389. /// </summary>
  390. public int LineNumber;
  391. /// <summary>
  392. /// Indicates that the document contains machine generated source code that should not show up in tools such as debuggers.
  393. /// Can be set by C# preprocessor directives.
  394. /// </summary>
  395. public bool Hidden;
  396. /// <summary>
  397. /// The name of the document. Typically a file name. Can be a full or relative file path, or a URI or some other kind of identifier.
  398. /// </summary>
  399. public string/*!*/ Name;
  400. /// <summary>
  401. /// Contains the source text.
  402. /// </summary>
  403. public DocumentText Text;
  404. public Document(){
  405. this.Name = "";
  406. //^ base();
  407. }
  408. public Document(string/*!*/ name, int lineNumber, string text, System.Guid documentType, System.Guid language, System.Guid languageVendor)
  409. :this(name, lineNumber, new DocumentText(text), documentType, language, languageVendor){
  410. }
  411. public Document(string/*!*/ name, int lineNumber, DocumentText text, System.Guid documentType, System.Guid language, System.Guid languageVendor) {
  412. this.DocumentType = documentType;
  413. this.Language = language;
  414. this.LanguageVendor = languageVendor;
  415. this.LineNumber = lineNumber;
  416. this.Name = name;
  417. this.Text = text;
  418. //^ base();
  419. }
  420. /// <summary>
  421. /// Maps the given zero based character position to the number of the source line containing the same character.
  422. /// Line number counting starts from the value of LineNumber.
  423. /// </summary>
  424. public virtual int GetLine(int position){
  425. int line = 0; int column = 0;
  426. this.GetPosition(position, out line, out column);
  427. return line+this.LineNumber;
  428. }
  429. /// <summary>
  430. /// Maps the given zero based character position in the entire text to the position of the same character in a source line.
  431. /// Counting within the source line starts at 1.
  432. /// </summary>
  433. public virtual int GetColumn(int position){
  434. int line = 0; int column = 0;
  435. this.GetPosition(position, out line, out column);
  436. return column+1;
  437. }
  438. /// <summary>
  439. /// Given a startLine, startColum, endLine and endColumn, this returns the corresponding startPos and endPos. In other words it
  440. /// converts a range expression in line and columns to a range expressed as a start and end character position.
  441. /// </summary>
  442. /// <param name="startLine">The number of the line containing the first character. The number of the first line equals this.LineNumber.</param>
  443. /// <param name="startColumn">The position of the first character relative to the start of the line. Counting from 1.</param>
  444. /// <param name="endLine">The number of the line contain the character that immediate follows the last character of the range.</param>
  445. /// <param name="endColumn">The position, in the last line, of the character that immediately follows the last character of the range.</param>
  446. /// <param name="startPos">The position in the entire text of the first character of the range, counting from 0.</param>
  447. /// <param name="endPos">The position in the entire text of the character following the last character of the range.</param>
  448. public virtual void GetOffsets(int startLine, int startColumn, int endLine, int endColumn, out int startPos, out int endPos){
  449. lock(this){
  450. if (this.lineOffsets == null) this.ComputeLineOffsets();
  451. //^ assert this.lineOffsets != null;
  452. startPos = this.lineOffsets[startLine-this.LineNumber]+startColumn-1;
  453. endPos = this.lineOffsets[endLine-this.LineNumber]+endColumn-1;
  454. }
  455. }
  456. /// <summary>
  457. /// Retrieves a substring from the text of this Document. The substring starts at a specified character position and has a specified length.
  458. /// </summary>
  459. public virtual string Substring(int position, int length){
  460. if (this.Text == null) return null;
  461. return this.Text.Substring(position, length);
  462. }
  463. /// <summary>
  464. /// Counts the number of end of line marker sequences in the given text.
  465. /// </summary>
  466. protected int GetLineCount(string/*!*/ text) {
  467. int n = text == null ? 0 : text.Length;
  468. int count = 0;
  469. for (int i = 0; i < n; i++){
  470. switch(text[i]){
  471. case '\r':
  472. if (i+1 < n && text[i+1] == '\n')
  473. i++;
  474. count++;
  475. break;
  476. case '\n':
  477. case (char)0x2028:
  478. case (char)0x2029:
  479. count++;
  480. break;
  481. }
  482. }
  483. return count;
  484. }
  485. /// <summary>An array of offsets, with offset at index i corresponding to the position of the first character of line i, (counting lines from 0).</summary>
  486. private int[] lineOffsets;
  487. /// <summary>The number of lines in Text.</summary>
  488. private int lines;
  489. /// <summary>
  490. /// Returns the index in this.lineOffsets array such that this.lineOffsets[index] is less than or equal to offset
  491. /// and offset is less than lineOffsets[index+1]
  492. /// </summary>
  493. private int Search(int offset){
  494. tryAgain:
  495. int[] lineOffsets = this.lineOffsets;
  496. int lines = this.lines;
  497. if (lineOffsets == null){Debug.Assert(false); return -1;}
  498. if (offset < 0){Debug.Assert(false); return -1;}
  499. int mid = 0;
  500. int low = 0;
  501. int high = lines-1;
  502. while (low < high){
  503. mid = (low+high)/2;
  504. if (lineOffsets[mid] <= offset){
  505. if (offset < lineOffsets[mid+1])
  506. return mid;
  507. else
  508. low = mid + 1;
  509. }else
  510. high = mid;
  511. }
  512. Debug.Assert(lines == this.lines);
  513. Debug.Assert(lineOffsets[low] <= offset);
  514. Debug.Assert(offset < lineOffsets[low+1]);
  515. if (lineOffsets != this.lineOffsets) goto tryAgain;
  516. return low;
  517. }
  518. /// <summary>
  519. /// Maps the given zero based character position in the entire text to a (line, column) pair corresponding to the same position.
  520. /// Counting within the source line starts at 0. Counting source lines start at 0.
  521. /// </summary>
  522. private void GetPosition(int offset, out int line, out int column){
  523. line = 0; column = 0;
  524. if (offset < 0 || this.Text == null || offset > this.Text.Length){Debug.Assert(false); return;}
  525. lock(this){
  526. if (this.lineOffsets == null) this.ComputeLineOffsets();
  527. if (this.lineOffsets == null){Debug.Assert(false); return;}
  528. int[] lineOffsets = this.lineOffsets;
  529. int index = this.Search(offset);
  530. Debug.Assert(lineOffsets == this.lineOffsets);
  531. if (index < 0 || index >= this.lineOffsets.Length){Debug.Assert(false); return;}
  532. Debug.Assert(this.lineOffsets[index] <= offset && offset < this.lineOffsets[index+1]);
  533. line = index;
  534. column = offset-this.lineOffsets[index];
  535. }
  536. }
  537. /// <summary>
  538. /// Adds the given offset to the this.lineOffsets table as the offset corresponding to the start of line this.lines+1.
  539. /// </summary>
  540. private void AddOffset(int offset){
  541. if (this.lineOffsets == null || this.lines < 0){Debug.Assert(false); return;}
  542. if (this.lines >= this.lineOffsets.Length){
  543. int n = this.lineOffsets.Length;
  544. if (n <= 0) n = 16;
  545. int[] newLineOffsets = new int[n*2];
  546. Array.Copy(this.lineOffsets, newLineOffsets, this.lineOffsets.Length);
  547. this.lineOffsets = newLineOffsets;
  548. }
  549. this.lineOffsets[this.lines++] = offset;
  550. }
  551. public virtual void InsertOrDeleteLines(int offset, int lineCount){
  552. if (lineCount == 0) return;
  553. if (offset < 0 || this.Text == null || offset > this.Text.Length){Debug.Assert(false); return;}
  554. lock(this){
  555. if (this.lineOffsets == null)
  556. if (this.lineOffsets == null) this.ComputeLineOffsets();
  557. if (lineCount < 0)
  558. this.DeleteLines(offset, -lineCount);
  559. else
  560. this.InsertLines(offset, lineCount);
  561. }
  562. }
  563. private void DeleteLines(int offset, int lineCount)
  564. //^ requires offset >= 0 && this.Text != null && offset < this.Text.Length && lineCount > 0 && this.lineOffsets != null;
  565. {
  566. Debug.Assert(offset >= 0 && this.Text != null && offset < this.Text.Length && lineCount > 0 && this.lineOffsets != null);
  567. int index = this.Search(offset);
  568. if (index < 0 || index >= this.lines){Debug.Assert(false); return;}
  569. for (int i = index+1; i+lineCount < this.lines; i++){
  570. this.lineOffsets[i] = this.lineOffsets[i+lineCount];
  571. }
  572. this.lines -= lineCount;
  573. if (this.lines <= index){Debug.Assert(false); this.lines = index+1;}
  574. }
  575. private void InsertLines(int offset, int lineCount)
  576. //^ requires offset >= 0 && this.Text != null && offset < this.Text.Length && lineCount > 0 && this.lineOffsets != null;
  577. {
  578. Debug.Assert(offset >= 0 && this.Text != null && offset < this.Text.Length && lineCount > 0 && this.lineOffsets != null);
  579. int index = this.Search(offset);
  580. if (index < 0 || index >= this.lines){Debug.Assert(false); return;}
  581. int n = this.lineOffsets[this.lines-1];
  582. for (int i = 0; i < lineCount; i++) this.AddOffset(++n);
  583. for (int i = lineCount; i > 0; i--){
  584. this.lineOffsets[index+i+1] = this.lineOffsets[index+1];
  585. }
  586. }
  587. /// <summary>
  588. /// Populates this.lineOffsets with an array of offsets, with offset at index i corresponding to the position of the first
  589. /// character of line i, (counting lines from 0).
  590. /// </summary>
  591. private void ComputeLineOffsets()
  592. //ensures this.lineOffsets != null;
  593. {
  594. if (this.Text == null){Debug.Assert(false); return;}
  595. int n = this.Text.Length;
  596. this.lineOffsets = new int[n/10+1];
  597. this.lines = 0;
  598. this.AddOffset(0);
  599. for (int i = 0; i < n; i++){
  600. switch(this.Text[i]){
  601. case '\r':
  602. if (i+1 < n && this.Text[i+1] == '\n')
  603. i++;
  604. this.AddOffset(i+1);
  605. break;
  606. case '\n':
  607. case (char)0x2028:
  608. case (char)0x2029:
  609. this.AddOffset(i+1);
  610. break;
  611. }
  612. }
  613. this.AddOffset(n+1);
  614. this.AddOffset(n+2);
  615. }
  616. /// <summary> Add one to this every time a Document instance gets a unique key.</summary>
  617. private static int uniqueKeyCounter;
  618. private int uniqueKey;
  619. /// <summary>
  620. /// An integer that uniquely distinguishes this document instance from every other document instance.
  621. /// This provides an efficient equality test to facilitate hashing.
  622. /// </summary>
  623. public int UniqueKey{
  624. get{
  625. if (this.uniqueKey == 0){
  626. TryAgain:
  627. int c = Document.uniqueKeyCounter;
  628. int cp1 = c == int.MaxValue ? 1 : c+1;
  629. if (System.Threading.Interlocked.CompareExchange(ref Document.uniqueKeyCounter, cp1, c) != c) goto TryAgain;
  630. this.uniqueKey = cp1;
  631. }
  632. return this.uniqueKey;
  633. }
  634. }
  635. }
  636. #endif
  637. #if !MinimalReader
  638. /// <summary>
  639. /// For creating source contexts that have just a filename, start line and column and end line and column.
  640. /// If a SourceContext has a DocumentWithPrecomputedLineNumbers as its Document, then it should have 0 as its StartPos
  641. /// and 1 as its EndPos because those are used here to decide what to return.
  642. /// </summary>
  643. public class DocumentWithPrecomputedLineNumbers : Document {
  644. private int startLine, startCol, endLine, endCol;
  645. public DocumentWithPrecomputedLineNumbers(string/*!*/ filename, int startLine, int startCol, int endLine, int endCol) {
  646. this.Name = filename;
  647. this.startLine = startLine;
  648. this.startCol = startCol;
  649. this.endLine = endLine;
  650. this.endCol = endCol;
  651. }
  652. public override int GetColumn (int offset) { return offset == 0 ? this.startCol : this.endCol; }
  653. public override int GetLine (int offset) { return offset == 0 ? this.startLine : this.endLine; }
  654. }
  655. #endif
  656. #if UseSingularityPDB
  657. internal class PdbDocument : Document {
  658. internal PdbDocument(PdbLines lines) {
  659. this.Name = lines.file.name;
  660. this.lines = lines;
  661. }
  662. PdbLines lines;
  663. public override int GetColumn(int position) {
  664. PdbLine line = this.lines.lines[position/2];
  665. if (position%2 == 0)
  666. return line.colBegin;
  667. else
  668. return line.colEnd;
  669. }
  670. public override int GetLine(int position) {
  671. PdbLine line = this.lines.lines[position/2];
  672. return (int)line.line;
  673. }
  674. }
  675. #elif !ROTOR
  676. internal class UnmanagedDocument: Document{
  677. internal UnmanagedDocument(IntPtr ptrToISymUnmanagedDocument){
  678. //^ base();
  679. ISymUnmanagedDocument idoc =
  680. (ISymUnmanagedDocument)System.Runtime.InteropServices.Marshal.GetTypedObjectForIUnknown(ptrToISymUnmanagedDocument, typeof(ISymUnmanagedDocument));
  681. if (idoc != null){
  682. try{
  683. #if !FxCop
  684. idoc.GetDocumentType(out this.DocumentType);
  685. idoc.GetLanguage(out this.Language);
  686. idoc.GetLanguageVendor(out this.LanguageVendor);
  687. #endif
  688. uint capacity = 1024;
  689. uint len = 0;
  690. char[] buffer = new char[capacity];
  691. while (capacity >= 1024){
  692. idoc.GetURL(capacity, out len, buffer);
  693. if (len < capacity) break;
  694. capacity += 1024;
  695. buffer = new char[capacity];
  696. }
  697. if (len > 0)
  698. this.Name = new String(buffer, 0, (int)len-1);
  699. }finally{
  700. System.Runtime.InteropServices.Marshal.ReleaseComObject(idoc);
  701. }
  702. }
  703. #if !FxCop
  704. this.LineNumber = -1;
  705. this.Text = null;
  706. #endif
  707. }
  708. private Int32List/*!*/ lineList = new Int32List();
  709. private Int32List/*!*/ columnList = new Int32List();
  710. #if !FxCop
  711. public override int GetLine(int offset){
  712. return this.lineList[offset];
  713. }
  714. public override int GetColumn(int offset){
  715. return this.columnList[offset];
  716. }
  717. public override void GetOffsets(int startLine, int startColumn, int endLine, int endColumn, out int startCol, out int endCol){
  718. int i = UnmanagedDocument.BinarySearch(this.lineList, startLine);
  719. Int32List columnList = this.columnList;
  720. startCol = 0;
  721. for (int j = i, n = columnList.Count; j < n; j++){
  722. if (columnList[j] >= startColumn){ startCol = j; break;}
  723. }
  724. endCol = 0;
  725. i = UnmanagedDocument.BinarySearch(this.lineList, endLine);
  726. for (int j = i, n = columnList.Count; j < n; j++){
  727. if (columnList[j] >= endColumn){ endCol = j; break;}
  728. }
  729. }
  730. private static int BinarySearch(Int32List/*!*/ list, int value){
  731. int mid = 0;
  732. int low = 0;
  733. int high = list.Count-1;
  734. while (low < high){
  735. mid = low + (high-low)/2;
  736. if (list[mid] <= value){
  737. if (list[mid+1] > value)
  738. return mid;
  739. else
  740. low = mid + 1;
  741. }else
  742. high = mid;
  743. }
  744. return low;
  745. }
  746. public override void InsertOrDeleteLines(int offset, int lineCount){
  747. Debug.Assert(false); //Caller should not be modifying an umanaged document
  748. }
  749. #endif
  750. internal int GetOffset(uint line, uint column){
  751. this.lineList.Add((int)line);
  752. this.columnList.Add((int)column);
  753. return this.lineList.Count-1;
  754. }
  755. }
  756. #endif // !ROTOR
  757. #if FxCop
  758. class Document{
  759. internal string Name;
  760. }
  761. public struct SourceContext{
  762. private string name;
  763. private int startLine;
  764. private int endLine;
  765. private int startColumn;
  766. private int endColumn;
  767. internal SourceContext(string name, uint startLine, uint endLine, uint startColumn, uint endColumn){
  768. this.name = name;
  769. checked {
  770. this.startLine = (int)startLine;
  771. this.endLine = (int)endLine;
  772. this.startColumn = (int)startColumn;
  773. this.endColumn = (int)endColumn;
  774. }
  775. }
  776. public string FileName{
  777. get{return this.name;}
  778. }
  779. public int StartLine{
  780. get{return this.startLine;}
  781. }
  782. public int EndLine{
  783. get{return this.endLine;}
  784. }
  785. public int StartColumn{
  786. get{return this.startColumn;}
  787. }
  788. public int EndColumn{
  789. get{return this.endColumn;}
  790. }
  791. }
  792. #else
  793. /// <summary>
  794. /// Records a location within a source document that corresponds to an Abstract Syntax Tree node.
  795. /// </summary>
  796. public struct SourceContext{
  797. /// <summary>The source document within which the AST node is located. Null if the node is not derived from a source document.</summary>
  798. public Document Document;
  799. /// <summary>
  800. /// The zero based index of the first character beyond the last character in the source document that corresponds to the AST node.
  801. /// </summary>
  802. public int EndPos;
  803. /// <summary>
  804. /// The zero based index of the first character in the source document that corresponds to the AST node.
  805. /// </summary>
  806. public int StartPos;
  807. public SourceContext(Document document)
  808. : this(document, 0, document == null ? 0 : (document.Text == null ? 0 : document.Text.Length)){
  809. }
  810. public SourceContext(Document document, int startPos, int endPos){
  811. this.Document = document;
  812. this.StartPos = startPos;
  813. this.EndPos = endPos;
  814. }
  815. public SourceContext(Document/*!*/ document,
  816. int startLine, int startColumn, int endLine, int endColumn){
  817. this.Document = document;
  818. this.Document.GetOffsets(startLine, startColumn, endLine, endColumn, out this.StartPos, out this.EndPos);
  819. }
  820. /// <summary>
  821. /// The number (counting from Document.LineNumber) of the line containing the first character in the source document that corresponds to the AST node.
  822. /// </summary>
  823. public int StartLine{
  824. get{
  825. if (this.Document == null) return 0;
  826. return this.Document.GetLine(this.StartPos);
  827. }
  828. }
  829. /// <summary>
  830. /// The number (counting from one) of the line column containing the first character in the source document that corresponds to the AST node.
  831. /// </summary>
  832. public int StartColumn{
  833. get{
  834. if (this.Document == null) return 0;
  835. return this.Document.GetColumn(this.StartPos);
  836. }
  837. }
  838. /// <summary>
  839. /// The number (counting from Document.LineNumber) of the line containing the first character beyond the last character in the source document that corresponds to the AST node.
  840. /// </summary>
  841. public int EndLine{
  842. get{
  843. #if UseSingularityPDB
  844. if (this.Document == null || (this.Document.Text == null && !(this.Document is PdbDocument))) return 0;
  845. #elif !ROTOR
  846. if (this.Document == null || (this.Document.Text == null && !(this.Document is UnmanagedDocument))) return 0;
  847. #else
  848. if (this.Document == null || this.Document.Text == null) return 0;
  849. #endif
  850. if (this.Document.Text != null && this.EndPos >= this.Document.Text.Length) this.EndPos = this.Document.Text.Length;
  851. return this.Document.GetLine(this.EndPos);
  852. }
  853. }
  854. /// <summary>
  855. /// The number (counting from one) of the line column containing first character beyond the last character in the source document that corresponds to the AST node.
  856. /// </summary>
  857. public int EndColumn{
  858. get{
  859. #if UseSingularityPDB
  860. if (this.Document == null || (this.Document.Text == null && !(this.Document is PdbDocument))) return 0;
  861. #elif !ROTOR
  862. if (this.Document == null || (this.Document.Text == null && !(this.Document is UnmanagedDocument))) return 0;
  863. #else
  864. if (this.Document == null || this.Document.Text == null) return 0;
  865. #endif
  866. if (this.Document.Text != null && this.EndPos >= this.Document.Text.Length) this.EndPos = this.Document.Text.Length;
  867. return this.Document.GetColumn(this.EndPos);
  868. }
  869. }
  870. /// <summary>
  871. /// Returns true if the line and column is greater than or equal the position of the first character
  872. /// and less than or equal to the position of the last character
  873. /// of the source document that corresponds to the AST node.
  874. /// </summary>
  875. /// <param name="line">A line number(counting from Document.LineNumber)</param>
  876. /// <param name="column">A column number (counting from one)</param>
  877. /// <returns></returns>
  878. public bool Encloses(int line, int column){
  879. if (line < this.StartLine || line > this.EndLine) return false;
  880. if (line == this.StartLine) return column >= this.StartColumn && (column <= this.EndColumn || line < this.EndLine);
  881. if (line == this.EndLine) return column <= this.EndColumn;
  882. return true;
  883. }
  884. public bool Encloses(SourceContext sourceContext){
  885. return this.StartPos <= sourceContext.StartPos && this.EndPos >= sourceContext.EndPos && this.EndPos > sourceContext.StartPos;
  886. }
  887. /// <summary>
  888. /// The substring of the source document that corresponds to the AST node.
  889. /// </summary>
  890. public string SourceText{
  891. get{
  892. if (this.Document == null) return null;
  893. return this.Document.Substring(this.StartPos, this.EndPos-this.StartPos);
  894. }
  895. }
  896. }
  897. #endif
  898. #if !MinimalReader
  899. public struct SourceChange{
  900. public SourceContext SourceContext;
  901. public string ChangedText;
  902. }
  903. /// <summary>
  904. /// Allows a compilation to output progress messages and to query if cancellation was requested.
  905. /// </summary>
  906. public class CompilerSite{
  907. public virtual void OutputMessage(string message){
  908. }
  909. public virtual bool ShouldCancel{
  910. get{
  911. return false;
  912. }
  913. }
  914. }
  915. #endif
  916. #if !NoWriter
  917. public enum PlatformType{notSpecified, v1, v11, v2, cli1}
  918. public class CompilerOptions: System.CodeDom.Compiler.CompilerParameters{
  919. public StringCollection AliasesForReferencedAssemblies;
  920. public ModuleKindFlags ModuleKind = ModuleKindFlags.ConsoleApplication;
  921. public bool EmitManifest = true;
  922. public StringList DefinedPreProcessorSymbols;
  923. public string XMLDocFileName;
  924. public string RecursiveWildcard;
  925. public StringList ReferencedModules;
  926. public string Win32Icon;
  927. #if !WHIDBEY
  928. private StringCollection embeddedResources = new StringCollection();
  929. public StringCollection EmbeddedResources{
  930. get{return this.embeddedResources;}
  931. }
  932. private StringCollection linkedResources = new StringCollection();
  933. public StringCollection LinkedResources{
  934. get{return this.linkedResources;}
  935. }
  936. #endif
  937. #if VS7
  938. private System.Security.Policy.Evidence evidence;
  939. public System.Security.Policy.Evidence Evidence{
  940. get{return this.evidence;}
  941. set{this.evidence = value;}
  942. }
  943. #endif
  944. public bool PDBOnly;
  945. public bool Optimize;
  946. public bool IncrementalCompile;
  947. public Int32List SuppressedWarnings;
  948. public bool CheckedArithmetic;
  949. public bool AllowUnsafeCode;
  950. public bool DisplayCommandLineHelp;
  951. public bool SuppressLogo;
  952. public long BaseAddress; //TODO: default value
  953. public string BugReportFileName;
  954. public object CodePage; //must be an int if not null
  955. public bool EncodeOutputInUTF8;
  956. public bool FullyQualifyPaths;
  957. public int FileAlignment;
  958. public bool NoStandardLibrary;
  959. public StringList AdditionalSearchPaths;
  960. public bool HeuristicReferenceResolution;
  961. public string RootNamespace;
  962. public bool CompileAndExecute;
  963. public object UserLocaleId; //must be an int if not null
  964. public string StandardLibraryLocation;
  965. public PlatformType TargetPlatform; //TODO: rename this to TargetRuntime
  966. #if !MinimalReader
  967. public ProcessorType TargetProcessor;
  968. #endif
  969. public string TargetPlatformLocation;
  970. public string AssemblyKeyFile;
  971. public string AssemblyKeyName;
  972. public bool DelaySign;
  973. public TargetInformation TargetInformation;
  974. public Int32List SpecificWarningsToTreatAsErrors;
  975. public Int32List SpecificWarningsNotToTreatAsErrors;
  976. public string OutputPath;
  977. public string ExplicitOutputExtension;
  978. public AppDomain TargetAppDomain;
  979. public bool MayLockFiles;
  980. public string ShadowedAssembly;
  981. public bool UseStandardConfigFile;
  982. #if !MinimalReader
  983. public CompilerSite Site;
  984. #endif
  985. #if ExtendedRuntime
  986. /// <summary>
  987. /// True if the source code for the assembly specify only contracts.
  988. /// </summary>
  989. public bool IsContractAssembly;
  990. /// <summary>
  991. /// Do not emit run-time checks for requires clauses of non-externally-accessible methods, assert statements, loop invariants, and ensures clauses.
  992. /// </summary>
  993. public bool DisableInternalChecks;
  994. /// <summary>
  995. /// Do not emit run-time checks for assume statements.
  996. /// </summary>
  997. public bool DisableAssumeChecks;
  998. /// <summary>
  999. /// Do not emit run-time checks for requires clauses of externally accessible methods.
  1000. /// Do not emit run-time checks that enforce checked exception policy.
  1001. /// </summary>
  1002. public bool DisableDefensiveChecks;
  1003. /// <summary>
  1004. /// Disable the guarded classes feature, which integrates run-time enforcement of object invariants, ownership, and safe concurrency.
  1005. /// </summary>
  1006. public bool DisableGuardedClassesChecks;
  1007. public bool DisableInternalContractsMetadata;
  1008. public bool DisablePublicContractsMetadata;
  1009. /// <summary>
  1010. /// Disable the runtime test against null on non-null typed parameters on public methods
  1011. /// </summary>
  1012. public bool DisableNullParameterValidation;
  1013. public virtual bool LoadDebugSymbolsForReferencedAssemblies {
  1014. get { return false; }
  1015. }
  1016. /// <summary>
  1017. /// If set, the compiler will only parse and then emit an xml file with detailed source contexts
  1018. /// about what is parsed.
  1019. /// </summary>
  1020. public bool EmitSourceContextsOnly = false;
  1021. #endif
  1022. public CompilerOptions(){
  1023. }
  1024. public CompilerOptions(CompilerOptions source){
  1025. if (source == null){Debug.Assert(false); return;}
  1026. this.AdditionalSearchPaths = source.AdditionalSearchPaths; //REVIEW: clone the list?
  1027. this.AliasesForReferencedAssemblies = source.AliasesForReferencedAssemblies;
  1028. this.AllowUnsafeCode = source.AllowUnsafeCode;
  1029. this.AssemblyKeyFile = source.AssemblyKeyFile;
  1030. this.AssemblyKeyName = source.AssemblyKeyName;
  1031. this.BaseAddress = source.BaseAddress;
  1032. this.BugReportFileName = source.BugReportFileName;
  1033. this.CheckedArithmetic = source.CheckedArithmetic;
  1034. this.CodePage = source.CodePage;
  1035. this.CompileAndExecute = source.CompileAndExecute;
  1036. this.CompilerOptions = source.CompilerOptions;
  1037. this.DefinedPreProcessorSymbols = source.DefinedPreProcessorSymbols;
  1038. this.DelaySign = source.DelaySign;
  1039. #if ExtendedRuntime
  1040. this.DisableAssumeChecks = source.DisableAssumeChecks;
  1041. this.DisableDefensiveChecks = source.DisableDefensiveChecks;
  1042. this.DisableGuardedClassesChecks = source.DisableGuardedClassesChecks;
  1043. this.DisableInternalChecks = source.DisableInternalChecks;
  1044. this.DisableInternalContractsMetadata = source.DisableInternalContractsMetadata;
  1045. this.DisablePublicContractsMetadata = source.DisablePublicContractsMetadata;
  1046. #endif
  1047. this.DisplayCommandLineHelp = source.DisplayCommandLineHelp;
  1048. if (source.EmbeddedResources != null)
  1049. foreach (string s in source.EmbeddedResources) this.EmbeddedResources.Add(s);
  1050. this.EmitManifest = source.EmitManifest;
  1051. this.EncodeOutputInUTF8 = source.EncodeOutputInUTF8;
  1052. this.Evidence = source.Evidence;
  1053. this.ExplicitOutputExtension = source.ExplicitOutputExtension;
  1054. this.FileAlignment = source.FileAlignment;
  1055. this.FullyQualifyPaths = source.FullyQualifyPaths;
  1056. this.GenerateExecutable = source.GenerateExecutable;
  1057. this.GenerateInMemory = source.GenerateInMemory;
  1058. this.HeuristicReferenceResolution = source.HeuristicReferenceResolution;
  1059. this.IncludeDebugInformation = source.IncludeDebugInformation;
  1060. this.IncrementalCompile = source.IncrementalCompile;
  1061. #if ExtendedRuntime
  1062. this.IsContractAssembly = source.IsContractAssembly;
  1063. #endif
  1064. if (source.LinkedResources != null)
  1065. foreach (string s in source.LinkedResources) this.LinkedResources.Add(s);
  1066. this.MainClass = source.MainClass;
  1067. this.MayLockFiles = source.MayLockFiles;
  1068. this.ModuleKind = source.ModuleKind;
  1069. this.NoStandardLibrary = source.NoStandardLibrary;
  1070. this.Optimize = source.Optimize;
  1071. this.OutputAssembly = source.OutputAssembly;
  1072. this.OutputPath = source.OutputPath;
  1073. this.PDBOnly = source.PDBOnly;
  1074. this.RecursiveWildcard = source.RecursiveWildcard;
  1075. if (source.ReferencedAssemblies != null)
  1076. foreach (string s in source.ReferencedAssemblies) this.ReferencedAssemblies.Add(s);
  1077. this.ReferencedModules = source.ReferencedModules;
  1078. this.RootNamespace = source.RootNamespace;
  1079. this.ShadowedAssembly = source.ShadowedAssembly;
  1080. this.SpecificWarningsToTreatAsErrors = source.SpecificWarningsToTreatAsErrors;
  1081. this.StandardLibraryLocation = source.StandardLibraryLocation;
  1082. this.SuppressLogo = source.SuppressLogo;
  1083. this.SuppressedWarnings = source.SuppressedWarnings;
  1084. this.TargetAppDomain = source.TargetAppDomain;
  1085. this.TargetInformation = source.TargetInformation;
  1086. this.TargetPlatform = source.TargetPlatform;
  1087. this.TargetPlatformLocation = source.TargetPlatformLocation;
  1088. this.TreatWarningsAsErrors = source.TreatWarningsAsErrors;
  1089. this.UserLocaleId = source.UserLocaleId;
  1090. this.UserToken = source.UserToken;
  1091. this.WarningLevel = source.WarningLevel;
  1092. this.Win32Icon = source.Win32Icon;
  1093. this.Win32Resource = source.Win32Resource;
  1094. this.XMLDocFileName = source.XMLDocFileName;
  1095. }
  1096. public virtual string GetOptionHelp(){
  1097. return null;
  1098. }
  1099. public virtual CompilerOptions Clone() {
  1100. return (CompilerOptions)this.MemberwiseClone();
  1101. }
  1102. }
  1103. #endif
  1104. public sealed class MarshallingInformation{
  1105. private string @class;
  1106. private string cookie;
  1107. private int elementSize;
  1108. private NativeType elementType;
  1109. private NativeType nativeType;
  1110. private int numberOfElements;
  1111. private int paramIndex;
  1112. private int size;
  1113. public MarshallingInformation Clone(){
  1114. return (MarshallingInformation)base.MemberwiseClone();
  1115. }
  1116. public string Class{
  1117. get{return this.@class;}
  1118. set{this.@class = value;}
  1119. }
  1120. public string Cookie{
  1121. get{return this.cookie;}
  1122. set{this.cookie = value;}
  1123. }
  1124. public int ElementSize{
  1125. get{return this.elementSize;}
  1126. set{this.elementSize = value;}
  1127. }
  1128. public NativeType ElementType{
  1129. get{return this.elementType;}
  1130. set{this.elementType = value;}
  1131. }
  1132. public NativeType NativeType{
  1133. get{return this.nativeType;}
  1134. set{this.nativeType = value;}
  1135. }
  1136. public int NumberOfElements{
  1137. get{return this.numberOfElements;}
  1138. set{this.numberOfElements = value;}
  1139. }
  1140. public int ParamIndex{
  1141. get{return this.paramIndex;}
  1142. set{this.paramIndex = value;}
  1143. }
  1144. public int Size{
  1145. get{return this.size;}
  1146. set{this.size = value;}
  1147. }
  1148. }
  1149. #if !NoWriter
  1150. public struct TargetInformation{
  1151. public string Company;
  1152. public string Configuration;
  1153. public string Copyright;
  1154. public string Culture;
  1155. public string Description;
  1156. public string Product;
  1157. public string ProductVersion;
  1158. public string Title;
  1159. public string Trademark;
  1160. public string Version;
  1161. }
  1162. #endif
  1163. public enum NativeType{
  1164. Bool = 0x2, // 4 byte boolean value (true != 0, false == 0)
  1165. I1 = 0x3, // 1 byte signed value
  1166. U1 = 0x4, // 1 byte unsigned value
  1167. I2 = 0x5, // 2 byte signed value
  1168. U2 = 0x6, // 2 byte unsigned value
  1169. I4 = 0x7, // 4 byte signed value
  1170. U4 = 0x8, // 4 byte unsigned value
  1171. I8 = 0x9, // 8 byte signed value
  1172. U8 = 0xa, // 8 byte unsigned value
  1173. R4 = 0xb, // 4 byte floating point
  1174. R8 = 0xc, // 8 byte floating point
  1175. Currency = 0xf, // A currency
  1176. BStr = 0x13, // OLE Unicode BSTR
  1177. LPStr = 0x14, // Ptr to SBCS string
  1178. LPWStr = 0x15, // Ptr to Unicode string
  1179. LPTStr = 0x16, // Ptr to OS preferred (SBCS/Unicode) string
  1180. ByValTStr = 0x17, // OS preferred (SBCS/Unicode) inline string (only valid in structs)
  1181. IUnknown = 0x19, // COM IUnknown pointer.
  1182. IDispatch = 0x1a, // COM IDispatch pointer
  1183. Struct = 0x1b, // Structure
  1184. Interface = 0x1c, // COM interface
  1185. SafeArray = 0x1d, // OLE SafeArray
  1186. ByValArray = 0x1e, // Array of fixed size (only valid in structs)
  1187. SysInt = 0x1f, // Hardware natural sized signed integer
  1188. SysUInt = 0x20,
  1189. VBByRefStr = 0x22,
  1190. AnsiBStr = 0x23, // OLE BSTR containing SBCS characters
  1191. TBStr = 0x24, // Ptr to OS preferred (SBCS/Unicode) BSTR
  1192. VariantBool = 0x25, // OLE defined BOOLEAN (2 bytes, true == -1, false == 0)
  1193. FunctionPtr = 0x26, // Function pointer
  1194. AsAny = 0x28, // Paired with Object type and does runtime marshalling determination
  1195. LPArray = 0x2a, // C style array
  1196. LPStruct = 0x2b, // Pointer to a structure
  1197. CustomMarshaler = 0x2c, // Native type supplied by custom code
  1198. Error = 0x2d,
  1199. NotSpecified = 0x50,
  1200. }
  1201. ///0-: Common
  1202. ///1000-: HScript
  1203. ///2000-: EcmaScript
  1204. ///3000-: Zonnon
  1205. ///4000-: Comega
  1206. ///5000-: X++
  1207. ///6000-: Spec#
  1208. ///7000-: Sing#
  1209. ///8000-: Xaml
  1210. ///9000-: C/AL
  1211. ///For your range contact hermanv@microsoft.com
  1212. public enum NodeType {
  1213. //Dummy
  1214. Undefined = 0,
  1215. //IL instruction node tags
  1216. Add,
  1217. Add_Ovf,
  1218. Add_Ovf_Un,
  1219. And,
  1220. Arglist,
  1221. Box,
  1222. Branch,
  1223. Call,
  1224. Calli,
  1225. Callvirt,
  1226. Castclass,
  1227. Ceq,
  1228. Cgt,
  1229. Cgt_Un,
  1230. Ckfinite,
  1231. Clt,
  1232. Clt_Un,
  1233. Conv_I,
  1234. Conv_I1,
  1235. Conv_I2,
  1236. Conv_I4,
  1237. Conv_I8,
  1238. Conv_Ovf_I,
  1239. Conv_Ovf_I_Un,
  1240. Conv_Ovf_I1,
  1241. Conv_Ovf_I1_Un,
  1242. Conv_Ovf_I2,
  1243. Conv_Ovf_I2_Un,
  1244. Conv_Ovf_I4,
  1245. Conv_Ovf_I4_Un,
  1246. Conv_Ovf_I8,
  1247. Conv_Ovf_I8_Un,
  1248. Conv_Ovf_U,
  1249. Conv_Ovf_U_Un,
  1250. Conv_Ovf_U1,
  1251. Conv_Ovf_U1_Un,
  1252. Conv_Ovf_U2,
  1253. Conv_Ovf_U2_Un,
  1254. Conv_Ovf_U4,
  1255. Conv_Ovf_U4_Un,
  1256. Conv_Ovf_U8,
  1257. Conv_Ovf_U8_Un,
  1258. Conv_R_Un,
  1259. Conv_R4,
  1260. Conv_R8,
  1261. Conv_U,
  1262. Conv_U1,
  1263. Conv_U2,
  1264. Conv_U4,
  1265. Conv_U8,
  1266. Cpblk,
  1267. DebugBreak,
  1268. Div,
  1269. Div_Un,
  1270. Dup,
  1271. EndFilter,
  1272. EndFinally,
  1273. ExceptionHandler,
  1274. Initblk,
  1275. Isinst,
  1276. Jmp,
  1277. Ldftn,
  1278. Ldlen,
  1279. Ldtoken,
  1280. Ldvirtftn,
  1281. Localloc,
  1282. Mkrefany,
  1283. Mul,
  1284. Mul_Ovf,
  1285. Mul_Ovf_Un,
  1286. Neg,
  1287. Nop,
  1288. Not,
  1289. Or,
  1290. Pop,
  1291. ReadOnlyAddressOf,
  1292. Refanytype,
  1293. Refanyval,
  1294. Rem,
  1295. Rem_Un,
  1296. Rethrow,
  1297. Shl,
  1298. Shr,
  1299. Shr_Un,
  1300. Sizeof,
  1301. SkipCheck,
  1302. Sub,
  1303. Sub_Ovf,
  1304. Sub_Ovf_Un,
  1305. SwitchInstruction,
  1306. Throw,
  1307. Unbox,
  1308. UnboxAny,
  1309. Xor,
  1310. //AST tags that are relevant to the binary reader
  1311. AddressDereference,
  1312. AddressOf,
  1313. AssignmentStatement,
  1314. Block,
  1315. Catch,
  1316. Construct,
  1317. ConstructArray,
  1318. Eq,
  1319. ExpressionStatement,
  1320. FaultHandler,
  1321. Filter,
  1322. Finally,
  1323. Ge,
  1324. Gt,
  1325. Identifier,
  1326. Indexer,
  1327. Instruction,
  1328. InterfaceExpression,
  1329. Le,
  1330. Literal,
  1331. LogicalNot,
  1332. Lt,
  1333. MemberBinding,
  1334. NamedArgument,
  1335. Namespace,
  1336. Ne,
  1337. Return,
  1338. This,
  1339. Try,
  1340. //Metadata node tags
  1341. ArrayType,
  1342. @Assembly,
  1343. AssemblyReference,
  1344. Attribute,
  1345. Class,
  1346. ClassParameter,
  1347. DelegateNode,
  1348. EnumNode,
  1349. Event,
  1350. Field,
  1351. FunctionPointer,
  1352. InstanceInitializer,
  1353. Interface,
  1354. Local,
  1355. Method,
  1356. Module,
  1357. ModuleReference,
  1358. OptionalModifier,
  1359. Parameter,
  1360. Pointer,
  1361. Property,
  1362. Reference,
  1363. RequiredModifier,
  1364. SecurityAttribute,
  1365. StaticInitializer,
  1366. Struct,
  1367. TypeParameter,
  1368. #if !MinimalReader
  1369. // The following NodeType definitions are not required
  1370. // for examining assembly metadata directly from binaries
  1371. //Serialization tags used for values that are not leaf nodes.
  1372. Array,
  1373. BlockReference,
  1374. CompilationParameters,
  1375. Document,
  1376. EndOfRecord,
  1377. Expression,
  1378. Guid,
  1379. List,
  1380. MarshallingInformation,
  1381. Member,
  1382. MemberReference,
  1383. MissingBlockReference,
  1384. MissingExpression,
  1385. MissingMemberReference,
  1386. String,
  1387. StringDictionary,
  1388. TypeNode,
  1389. Uri,
  1390. XmlNode,
  1391. //Source-based AST node tags
  1392. AddEventHandler,
  1393. AliasDefinition,
  1394. AnonymousNestedFunction,
  1395. ApplyToAll,
  1396. ArglistArgumentExpression,
  1397. ArglistExpression,
  1398. ArrayTypeExpression,
  1399. As,
  1400. Assertion,
  1401. AssignmentExpression,
  1402. Assumption,
  1403. Base,
  1404. #endif
  1405. #if FxCop
  1406. BlockExpression,
  1407. StackVariable,
  1408. #endif
  1409. #if !MinimalReader
  1410. BlockExpression,
  1411. BoxedTypeExpression,
  1412. ClassExpression,
  1413. CoerceTuple,
  1414. CollectionEnumerator,
  1415. Comma,
  1416. Compilation,
  1417. CompilationUnit,
  1418. CompilationUnitSnippet,
  1419. Conditional,
  1420. ConstructDelegate,
  1421. ConstructFlexArray,
  1422. ConstructIterator,
  1423. ConstructTuple,
  1424. Continue,
  1425. CopyReference,
  1426. CurrentClosure,
  1427. Decrement,
  1428. DefaultValue,
  1429. DoWhile,
  1430. Exit,
  1431. ExplicitCoercion,
  1432. ExpressionSnippet,
  1433. FieldInitializerBlock,
  1434. Fixed,
  1435. FlexArrayTypeExpression,
  1436. For,
  1437. ForEach,
  1438. FunctionDeclaration,
  1439. FunctionTypeExpression,
  1440. Goto,
  1441. GotoCase,
  1442. If,
  1443. ImplicitThis,
  1444. Increment,
  1445. InvariantTypeExpression,
  1446. Is,
  1447. LabeledStatement,
  1448. LocalDeclaration,
  1449. LocalDeclarationsStatement,
  1450. Lock,
  1451. LogicalAnd,
  1452. LogicalOr,
  1453. LRExpression,
  1454. MethodCall,
  1455. NameBinding,
  1456. NonEmptyStreamTypeExpression,
  1457. NonNullableTypeExpression,
  1458. NonNullTypeExpression,
  1459. NullableTypeExpression,
  1460. NullCoalescingExpression,
  1461. OutAddress,
  1462. Parentheses,
  1463. PointerTypeExpression,
  1464. PostfixExpression,
  1465. PrefixExpression,
  1466. QualifiedIdentifer,
  1467. RefAddress,
  1468. ReferenceTypeExpression,
  1469. RefTypeExpression,
  1470. RefValueExpression,
  1471. RemoveEventHandler,
  1472. Repeat,
  1473. ResourceUse,
  1474. SetterValue,
  1475. StackAlloc,
  1476. StatementSnippet,
  1477. StreamTypeExpression,
  1478. Switch,
  1479. SwitchCase,
  1480. SwitchCaseBottom,
  1481. TemplateInstance,
  1482. TupleTypeExpression,
  1483. TypeExpression,
  1484. TypeIntersectionExpression,
  1485. TypeMemberSnippet,
  1486. Typeof,
  1487. TypeReference,
  1488. Typeswitch,
  1489. TypeswitchCase,
  1490. TypeUnionExpression,
  1491. UnaryPlus,
  1492. UsedNamespace,
  1493. VariableDeclaration,
  1494. While,
  1495. Yield,
  1496. //Extended metadata node tags
  1497. ConstrainedType,
  1498. TupleType,
  1499. TypeAlias,
  1500. TypeIntersection,
  1501. TypeUnion,
  1502. //Query node tags
  1503. Composition,
  1504. QueryAggregate,
  1505. QueryAlias,
  1506. QueryAll,
  1507. QueryAny,
  1508. QueryAxis,
  1509. QueryCommit,
  1510. QueryContext,
  1511. QueryDelete,
  1512. QueryDifference,
  1513. QueryDistinct,
  1514. QueryExists,
  1515. QueryFilter,
  1516. QueryGeneratedType,
  1517. QueryGroupBy,
  1518. QueryInsert,
  1519. QueryIntersection,
  1520. QueryIterator,
  1521. QueryJoin,
  1522. QueryLimit,
  1523. QueryOrderBy,
  1524. QueryOrderItem,
  1525. QueryPosition,
  1526. QueryProject,
  1527. QueryQuantifiedExpression,
  1528. QueryRollback,
  1529. QuerySelect,
  1530. QuerySingleton,
  1531. QueryTransact,
  1532. QueryTypeFilter,
  1533. QueryUnion,
  1534. QueryUpdate,
  1535. QueryYielder,
  1536. //Contract node tags
  1537. Acquire,
  1538. Comprehension,
  1539. ComprehensionBinding,
  1540. Ensures,
  1541. EnsuresExceptional,
  1542. EnsuresNormal,
  1543. Iff,
  1544. Implies,
  1545. Invariant,
  1546. LogicalEqual,
  1547. LogicalImply,
  1548. Maplet,
  1549. MethodContract,
  1550. Modelfield,
  1551. ModelfieldContract,
  1552. OldExpression,
  1553. Range,
  1554. Read,
  1555. Requires,
  1556. RequiresOtherwise,
  1557. RequiresPlain,
  1558. ReturnValue,
  1559. TypeContract,
  1560. Write,
  1561. //Node tags for explicit modifiers in front-end
  1562. OptionalModifierTypeExpression,
  1563. RequiredModifierTypeExpression,
  1564. //Temporary node tags
  1565. Count,
  1566. Exists,
  1567. ExistsUnique,
  1568. Forall,
  1569. Max,
  1570. Min,
  1571. Product,
  1572. Sum,
  1573. Quantifier,
  1574. #endif // MinimalReader
  1575. }
  1576. [Flags]
  1577. public enum AssemblyFlags{
  1578. None = 0x0000,
  1579. PublicKey = 0x0001,
  1580. Library = 0x0002,
  1581. Platform = 0x0004,
  1582. NowPlatform = 0x0006,
  1583. SideBySideCompatible = 0x0000,
  1584. NonSideBySideCompatible = 0x0010,
  1585. NonSideBySideProcess = 0x0020,
  1586. NonSideBySideMachine = 0x0030,
  1587. CompatibilityMask = 0x00F0,
  1588. Retargetable = 0x0100,
  1589. DisableJITcompileOptimizer = 0x4000,
  1590. EnableJITcompileTracking = 0x8000
  1591. }
  1592. public enum AssemblyHashAlgorithm{
  1593. None = 0x0000,
  1594. MD5 = 0x8003,
  1595. SHA1 = 0x8004
  1596. }
  1597. [Flags]
  1598. public enum CallingConventionFlags{
  1599. Default = 0x0,
  1600. C = 0x1,
  1601. StandardCall = 0x2,
  1602. ThisCall = 0x3,
  1603. FastCall = 0x4,
  1604. VarArg = 0x5,
  1605. ArgumentConvention = 0x7,
  1606. Generic = 0x10,
  1607. HasThis = 0x20,
  1608. ExplicitThis = 0x40
  1609. }
  1610. [Flags]
  1611. public enum EventFlags{
  1612. None = 0x0000,
  1613. SpecialName = 0x0200,
  1614. ReservedMask = 0x0400,
  1615. RTSpecialName = 0x0400,
  1616. #if !MinimalReader
  1617. Extend = MethodFlags.Extend, // used for languages with type extensions, e.g. Sing#
  1618. #endif
  1619. }
  1620. [Flags]
  1621. public enum FieldFlags{
  1622. None = 0x0000,
  1623. FieldAccessMask = 0x0007,
  1624. CompilerControlled = 0x0000,
  1625. Private = 0x0001,
  1626. FamANDAssem = 0x0002,
  1627. Assembly = 0x0003,
  1628. Family = 0x0004,
  1629. FamORAssem = 0x0005,
  1630. Public = 0x0006,
  1631. Static = 0x0010,
  1632. InitOnly = 0x0020,
  1633. Literal = 0x0040,
  1634. NotSerialized = 0x0080,
  1635. SpecialName = 0x0200,
  1636. PinvokeImpl = 0x2000,
  1637. ReservedMask = 0x9500,
  1638. RTSpecialName = 0x0400,
  1639. HasFieldMarshal = 0x1000,
  1640. HasDefault = 0x8000,
  1641. HasFieldRVA = 0x0100,
  1642. }
  1643. [Flags]
  1644. public enum FileFlags{
  1645. ContainsMetaData = 0x0000,
  1646. ContainsNoMetaData = 0x0001
  1647. }
  1648. [Flags]
  1649. public enum TypeParameterFlags{
  1650. NonVariant = 0x0000,
  1651. Covariant = 0x0001,
  1652. Contravariant = 0x0002,
  1653. VarianceMask = 0x0003,
  1654. NoSpecialConstraint = 0x0000,
  1655. ReferenceTypeConstraint = 0x0004,
  1656. ValueTypeConstraint = 0x0008,
  1657. DefaultConstructorConstraint = 0x0010,
  1658. SpecialConstraintMask = 0x001C,
  1659. }
  1660. [Flags]
  1661. public enum MethodImplFlags{
  1662. CodeTypeMask = 0x0003,
  1663. IL = 0x0000,
  1664. Native = 0x0001,
  1665. OPTIL = 0x0002,
  1666. Runtime = 0x0003,
  1667. ManagedMask = 0x0004,
  1668. Unmanaged = 0x0004,
  1669. Managed = 0x0000,
  1670. ForwardRef = 0x0010,
  1671. PreserveSig = 0x0080,
  1672. InternalCall = 0x1000,
  1673. Synchronized = 0x0020,
  1674. NoInlining = 0x0008,
  1675. #if !MinimalReader
  1676. MaxMethodImplVal = 0xffff
  1677. #endif
  1678. }
  1679. [Flags]
  1680. public enum MethodFlags{
  1681. MethodAccessMask = 0x0007,
  1682. CompilerControlled = 0x0000,
  1683. Private = 0x0001,
  1684. FamANDAssem = 0x0002,
  1685. Assembly = 0x0003,
  1686. Family = 0x0004,
  1687. FamORAssem = 0x0005,
  1688. Public = 0x0006,
  1689. Static = 0x0010,
  1690. Final = 0x0020,
  1691. Virtual = 0x0040,
  1692. HideBySig = 0x0080,
  1693. VtableLayoutMask = 0x0100,
  1694. ReuseSlot = 0x0000,
  1695. NewSlot = 0x0100,
  1696. CheckAccessOnOverride = 0x0200,
  1697. Abstract = 0x0400,
  1698. SpecialName = 0x0800,
  1699. PInvokeImpl = 0x2000,
  1700. UnmanagedExport = 0xd000,
  1701. ReservedMask = 0xd000,
  1702. RTSpecialName = 0x1000,
  1703. HasSecurity = 0x4000,
  1704. RequireSecObject = 0x8000,
  1705. #if !MinimalReader
  1706. Extend = 0x01000000, // used for languages with type extensions, e.g. Sing#
  1707. #endif
  1708. }
  1709. public enum ModuleKindFlags{ //TODO: rename this to just ModuleKind
  1710. ConsoleApplication,
  1711. WindowsApplication,
  1712. DynamicallyLinkedLibrary,
  1713. ManifestResourceFile,
  1714. UnmanagedDynamicallyLinkedLibrary
  1715. }
  1716. [Flags]
  1717. public enum ParameterFlags{
  1718. None = 0x0000,
  1719. In = 0x0001,
  1720. Out = 0x0002,
  1721. Optional = 0x0010,
  1722. ReservedMask = 0xf000,
  1723. HasDefault = 0x1000,
  1724. HasFieldMarshal = 0x2000
  1725. }
  1726. [Flags]
  1727. public enum PEKindFlags{
  1728. ILonly = 0x0001,
  1729. Requires32bits = 0x0002,
  1730. Requires64bits = 0x0004,
  1731. AMD = 0x0008
  1732. }
  1733. [Flags]
  1734. public enum PInvokeFlags{
  1735. None = 0x0000,
  1736. NoMangle = 0x0001,
  1737. BestFitDisabled = 0x0020,
  1738. BestFitEnabled = 0x0010,
  1739. BestFitUseAsm = 0x0000,
  1740. BestFitMask = 0x0030,
  1741. CharSetMask = 0x0006,
  1742. CharSetNotSpec = 0x0000,
  1743. CharSetAns = 0x0002,
  1744. CharSetUnicode = 0x0004,
  1745. CharSetAuto = 0x0006,
  1746. SupportsLastError = 0x0040,
  1747. CallingConvMask = 0x0700,
  1748. CallConvWinapi = 0x0100,
  1749. CallConvCdecl = 0x0200,
  1750. CallConvStdcall = 0x0300,
  1751. CallConvThiscall = 0x0400,
  1752. CallConvFastcall = 0x0500,
  1753. ThrowOnUnmappableCharMask = 0x3000,
  1754. ThrowOnUnmappableCharEnabled = 0x1000,
  1755. ThrowOnUnmappableCharDisabled = 0x2000,
  1756. ThrowOnUnmappableCharUseAsm = 0x0000
  1757. }
  1758. [Flags]
  1759. public enum PropertyFlags{
  1760. None = 0x0000,
  1761. SpecialName = 0x0200,
  1762. ReservedMask = 0xf400,
  1763. RTSpecialName = 0x0400,
  1764. #if !MinimalReader
  1765. Extend = MethodFlags.Extend, // used for languages with type extensions, e.g. Sing#
  1766. #endif
  1767. }
  1768. public enum PESection{
  1769. Text,
  1770. SData,
  1771. TLS
  1772. };
  1773. #if !MinimalReader
  1774. public enum ProcessorType{
  1775. Any,
  1776. x86,
  1777. x64,
  1778. Itanium,
  1779. }
  1780. #endif
  1781. [Flags]
  1782. public enum TypeFlags{
  1783. None = 0x00000000,
  1784. VisibilityMask = 0x00000007,
  1785. NotPublic = 0x00000000,
  1786. Public = 0x00000001,
  1787. NestedPublic = 0x00000002,
  1788. NestedPrivate = 0x00000003,
  1789. NestedFamily = 0x00000004,
  1790. NestedAssembly = 0x00000005,
  1791. NestedFamANDAssem = 0x00000006,
  1792. NestedFamORAssem = 0x00000007,
  1793. LayoutMask = 0x00000018,
  1794. AutoLayout = 0x00000000,
  1795. SequentialLayout = 0x00000008,
  1796. ExplicitLayout = 0x00000010,
  1797. ClassSemanticsMask= 0x00000020,
  1798. Class = 0x00000000,
  1799. Interface = 0x00000020,
  1800. LayoutOverridden = 0x00000040, // even AutoLayout can be explicit or implicit
  1801. Abstract = 0x00000080,
  1802. Sealed = 0x00000100,
  1803. SpecialName = 0x00000400,
  1804. Import = 0x00001000,
  1805. Serializable = 0x00002000,
  1806. StringFormatMask = 0x00030000,
  1807. AnsiClass = 0x00000000,
  1808. UnicodeClass = 0x00010000,
  1809. AutoClass = 0x00020000,
  1810. BeforeFieldInit = 0x00100000,
  1811. ReservedMask = 0x00040800,
  1812. RTSpecialName = 0x00000800,
  1813. HasSecurity = 0x00040000,
  1814. Forwarder = 0x00200000, //The type is a stub left behind for backwards compatibility. References to this type are forwarded to another type by the CLR.
  1815. #if !MinimalReader
  1816. Extend = 0x01000000, // used for languages with type extensions, e.g. Sing#
  1817. #endif
  1818. }
  1819. public sealed class TrivialHashtable{
  1820. struct HashEntry {
  1821. public int Key;
  1822. public object Value;
  1823. }
  1824. private HashEntry[]/*!*/ entries;
  1825. private int count;
  1826. public TrivialHashtable(){
  1827. this.entries = new HashEntry[16];
  1828. //this.count = 0;
  1829. }
  1830. private TrivialHashtable(HashEntry[]/*!*/ entries, int count) {
  1831. this.entries = entries;
  1832. this.count = count;
  1833. }
  1834. public TrivialHashtable(int expectedEntries) {
  1835. int initialSize = 16;
  1836. expectedEntries <<= 1;
  1837. while (initialSize < expectedEntries && initialSize > 0) initialSize <<= 1;
  1838. if (initialSize < 0) initialSize = 16;
  1839. this.entries = new HashEntry[initialSize];
  1840. //this.count = 0;
  1841. }
  1842. public int Count{
  1843. get{
  1844. return this.count;
  1845. }
  1846. }
  1847. private void Expand(){
  1848. HashEntry[] oldEntries = this.entries;
  1849. int n = oldEntries.Length;
  1850. int m = n*2;
  1851. if (m <= 0) return;
  1852. HashEntry[] entries = new HashEntry[m];
  1853. int count = 0;
  1854. for (int i = 0; i < n; i++){
  1855. int key = oldEntries[i].Key;
  1856. if (key <= 0) continue; //No entry (0) or deleted entry (-1)
  1857. object value = oldEntries[i].Value;
  1858. Debug.Assert(value != null);
  1859. int j = key & (m-1);
  1860. int k = entries[j].Key;
  1861. while (true){
  1862. if (k == 0){
  1863. entries[j].Value = value;
  1864. entries[j].Key = key;
  1865. count++;
  1866. break;
  1867. }
  1868. j++; if (j >= m) j = 0;
  1869. k = entries[j].Key;
  1870. }
  1871. }
  1872. this.entries = entries;
  1873. this.count = count;
  1874. }
  1875. public object this[int key]{
  1876. get{
  1877. if (key <= 0) throw new ArgumentException(ExceptionStrings.KeyNeedsToBeGreaterThanZero, "key");
  1878. HashEntry[] entries = this.entries;
  1879. int n = entries.Length;
  1880. int i = key & (n-1);
  1881. int k = entries[i].Key;
  1882. object result = null;
  1883. while (true){
  1884. if (k == key){result = entries[i].Value; break;}
  1885. if (k == 0) break;
  1886. i++; if (i >= n) i = 0;
  1887. k = entries[i].Key;
  1888. }
  1889. return result;
  1890. }
  1891. set{
  1892. if (key <= 0) throw new ArgumentException(ExceptionStrings.KeyNeedsToBeGreaterThanZero, "key");
  1893. HashEntry[] entries = this.entries;
  1894. int n = entries.Length;
  1895. int i = key & (n-1);
  1896. int k = entries[i].Key;
  1897. while(true){
  1898. if (k == key || k == 0){
  1899. entries[i].Value = value;
  1900. if (k == 0){
  1901. if (value == null){return;}
  1902. entries[i].Key = key;
  1903. if (++this.count > n/2) this.Expand();
  1904. return;
  1905. }
  1906. if (value == null) entries[i].Key = -1;
  1907. return;
  1908. }
  1909. i++; if (i >= n) i = 0;
  1910. k = entries[i].Key;
  1911. }
  1912. }
  1913. }
  1914. public TrivialHashtable Clone(){
  1915. HashEntry[] clonedEntries = (HashEntry[]) this.entries.Clone();
  1916. //^ assume clonedEntries != null;
  1917. return new TrivialHashtable(clonedEntries, this.count);
  1918. }
  1919. }
  1920. #if !FxCop
  1921. public
  1922. #endif
  1923. sealed class TrivialHashtableUsingWeakReferences{
  1924. struct HashEntry {
  1925. public int Key;
  1926. public WeakReference Value;
  1927. }
  1928. private HashEntry[]/*!*/ entries;
  1929. private int count;
  1930. public TrivialHashtableUsingWeakReferences(){
  1931. this.entries = new HashEntry[16];
  1932. //this.count = 0;
  1933. }
  1934. private TrivialHashtableUsingWeakReferences(HashEntry[]/*!*/ entries, int count) {
  1935. this.entries = entries;
  1936. this.count = count;
  1937. }
  1938. public TrivialHashtableUsingWeakReferences(int expectedEntries) {
  1939. int initialSize = 16;
  1940. expectedEntries <<= 1;
  1941. while (initialSize < expectedEntries && initialSize > 0) initialSize <<= 1;
  1942. if (initialSize < 0) initialSize = 16;
  1943. this.entries = new HashEntry[initialSize];
  1944. //this.count = 0;
  1945. }
  1946. public int Count{
  1947. get{
  1948. return this.count;
  1949. }
  1950. }
  1951. private void Expand(){
  1952. HashEntry[] oldEntries = this.entries;
  1953. int n = oldEntries.Length;
  1954. int m = n*2;
  1955. if (m <= 0) return;
  1956. HashEntry[] entries = new HashEntry[m];
  1957. int count = 0;
  1958. for (int i = 0; i < n; i++){
  1959. int key = oldEntries[i].Key;
  1960. if (key <= 0) continue; //No entry (0) or deleted entry (-1)
  1961. WeakReference value = oldEntries[i].Value;
  1962. Debug.Assert(value != null);
  1963. if (value == null || !value.IsAlive) continue; //Collected entry.
  1964. int j = key & (m-1);
  1965. int k = entries[j].Key;
  1966. while (true){
  1967. if (k == 0){
  1968. entries[j].Value = value;
  1969. entries[j].Key = key;
  1970. count++;
  1971. break;
  1972. }
  1973. j++; if (j >= m) j = 0;
  1974. k = entries[j].Key;
  1975. }
  1976. }
  1977. this.entries = entries;
  1978. this.count = count;
  1979. }
  1980. private void Contract() {
  1981. HashEntry[] oldEntries = this.entries;
  1982. int n = oldEntries.Length;
  1983. int m = n/2;
  1984. if (m < 16) return;
  1985. HashEntry[] entries = new HashEntry[m];
  1986. int count = 0;
  1987. for (int i = 0; i < n; i++) {
  1988. int key = oldEntries[i].Key;
  1989. if (key <= 0) continue; //No entry (0) or deleted entry (-1)
  1990. WeakReference value = oldEntries[i].Value;
  1991. Debug.Assert(value != null);
  1992. if (value == null || !value.IsAlive) continue; //Collected entry.
  1993. int j = key & (m-1);
  1994. int k = entries[j].Key;
  1995. while (true) {
  1996. if (k == 0) {
  1997. entries[j].Value = value;
  1998. entries[j].Key = key;
  1999. count++;
  2000. break;
  2001. }
  2002. j++; if (j >= m) j = 0;
  2003. k = entries[j].Key;
  2004. }
  2005. }
  2006. this.entries = entries;
  2007. this.count = count;
  2008. }
  2009. private void WeedOutCollectedEntries() {
  2010. HashEntry[] oldEntries = this.entries;
  2011. int n = oldEntries.Length;
  2012. HashEntry[] entries = new HashEntry[n];
  2013. int count = 0;
  2014. for (int i = 0; i < n; i++) {
  2015. int key = oldEntries[i].Key;
  2016. if (key <= 0) continue; //No entry (0) or deleted entry (-1)
  2017. WeakReference value = oldEntries[i].Value;
  2018. Debug.Assert(value != null);
  2019. if (value == null || !value.IsAlive) continue; //Collected entry.
  2020. int j = key & (n-1);
  2021. int k = entries[j].Key;
  2022. while (true) {
  2023. if (k == 0) {
  2024. entries[j].Value = value;
  2025. entries[j].Key = key;
  2026. count++;
  2027. break;
  2028. }
  2029. j++; if (j >= n) j = 0;
  2030. k = entries[j].Key;
  2031. }
  2032. }
  2033. this.entries = entries;
  2034. this.count = count;
  2035. }
  2036. public object this[int key] {
  2037. get{
  2038. if (key <= 0) throw new ArgumentException(ExceptionStrings.KeyNeedsToBeGreaterThanZero, "key");
  2039. HashEntry[] entries = this.entries;
  2040. int n = entries.Length;
  2041. int i = key & (n-1);
  2042. int k = entries[i].Key;
  2043. object result = null;
  2044. while (true){
  2045. if (k == key){
  2046. WeakReference wref = entries[i].Value;
  2047. if (wref == null) { Debug.Assert(false); return null; }
  2048. result = wref.Target;
  2049. if (result != null) return result;
  2050. this.WeedOutCollectedEntries();
  2051. while (this.count < n/4 && n > 16) { this.Contract(); n = this.entries.Length; }
  2052. return null;
  2053. }
  2054. if (k == 0) break;
  2055. i++; if (i >= n) i = 0;
  2056. k = entries[i].Key;
  2057. }
  2058. return result;
  2059. }
  2060. set{
  2061. if (key <= 0) throw new ArgumentException(ExceptionStrings.KeyNeedsToBeGreaterThanZero, "key");
  2062. HashEntry[] entries = this.entries;
  2063. int n = entries.Length;
  2064. int i = key & (n-1);
  2065. int k = entries[i].Key;
  2066. while(true){
  2067. if (k == key || k == 0) {
  2068. if (value == null)
  2069. entries[i].Value = null;
  2070. else
  2071. entries[i].Value = new WeakReference(value);
  2072. if (k == 0) {
  2073. if (value == null) return;
  2074. entries[i].Key = key;
  2075. if (++this.count > n/2) {
  2076. this.Expand(); //Could decrease this.count because of collected entries being deleted
  2077. while (this.count < n/4 && n > 16) { this.Contract(); n = this.entries.Length; }
  2078. }
  2079. return;
  2080. }
  2081. if (value == null) entries[i].Key = -1;
  2082. return;
  2083. }
  2084. i++; if (i >= n) i = 0;
  2085. k = entries[i].Key;
  2086. }
  2087. }
  2088. }
  2089. public TrivialHashtableUsingWeakReferences Clone() {
  2090. HashEntry[] clonedEntries = (HashEntry[]) this.entries.Clone();
  2091. //^ assume clonedEntries != null;
  2092. return new TrivialHashtableUsingWeakReferences(clonedEntries, this.count);
  2093. }
  2094. }
  2095. public interface IUniqueKey{
  2096. int UniqueId{get;}
  2097. }
  2098. /// <summary>
  2099. /// A node in an Abstract Syntax Tree.
  2100. /// </summary>
  2101. public abstract class Node : IUniqueKey{
  2102. #if !MinimalReader
  2103. public bool IsErroneous;
  2104. #endif
  2105. /// <summary>
  2106. /// The region in the source code that contains the concrete syntax corresponding to this node in the Abstract Syntax Tree.
  2107. /// </summary>
  2108. #if !FxCop
  2109. public SourceContext SourceContext;
  2110. #else
  2111. internal SourceContext sourceContext;
  2112. public SourceContext SourceContext {
  2113. get{return this.sourceContext;}
  2114. internal set{this.sourceContext = value;}
  2115. }
  2116. #endif
  2117. #if DEBUG && !MinimalReader
  2118. public string DebugLabel; // useful for debugging.
  2119. #endif
  2120. protected Node(NodeType nodeType){
  2121. this.NodeType = nodeType;
  2122. }
  2123. private NodeType nodeType;
  2124. /// <summary>
  2125. /// A scalar tag that identifies the concrete type of the node. This is provided to allow efficient type membership tests that
  2126. /// facilitate tree traversal.
  2127. /// </summary>
  2128. public NodeType NodeType{
  2129. get{return this.nodeType;}
  2130. set{this.nodeType = value;}
  2131. }
  2132. private static int uniqueKeyCounter;
  2133. private int uniqueKey;
  2134. /// <summary>
  2135. /// An integer that uniquely identifies this node. This provides an efficient equality test to facilitate hashing.
  2136. /// Do not override this.
  2137. /// </summary>
  2138. public virtual int UniqueKey{
  2139. get{
  2140. if (this.uniqueKey == 0){
  2141. TryAgain:
  2142. int c = Node.uniqueKeyCounter;
  2143. int cp1 = c+17;
  2144. if (cp1 <= 0) cp1 = 1000000;
  2145. if (System.Threading.Interlocked.CompareExchange(ref Node.uniqueKeyCounter, cp1, c) != c) goto TryAgain;
  2146. this.uniqueKey = cp1;
  2147. }
  2148. return this.uniqueKey;
  2149. }
  2150. }
  2151. /// <summary>
  2152. /// Makes a shallow copy of the node.
  2153. /// </summary>
  2154. /// <returns>A shallow copy of the node</returns>
  2155. public virtual Node/*!*/ Clone() {
  2156. Node result = (Node)this.MemberwiseClone();
  2157. result.uniqueKey = 0;
  2158. return result;
  2159. }
  2160. #if !MinimalReader
  2161. public virtual object GetVisitorFor(object/*!*/ callingVisitor, string/*!*/ visitorClassName) {
  2162. if (callingVisitor == null || visitorClassName == null) { Debug.Fail(""); return null; }
  2163. return Node.GetVisitorFor(this.GetType(), callingVisitor, visitorClassName);
  2164. }
  2165. private static Hashtable VisitorTypeFor; //contains weak references
  2166. private static Object GetVisitorFor(System.Type/*!*/ nodeType, object/*!*/ callingVisitor, string/*!*/ visitorClassName) {
  2167. if (nodeType == null || callingVisitor == null || visitorClassName == null){Debug.Fail(""); return null;}
  2168. if (Node.VisitorTypeFor == null) Node.VisitorTypeFor = new Hashtable();
  2169. string customVisitorClassName = visitorClassName;
  2170. if (visitorClassName.IndexOf('.') < 0) customVisitorClassName = nodeType.Namespace + "." + visitorClassName;
  2171. if (customVisitorClassName == callingVisitor.GetType().FullName){
  2172. Debug.Assert(false); //This must be a bug, the calling visitor is the one that should handle the nodeType
  2173. return null;
  2174. }
  2175. System.Reflection.AssemblyName visitorAssemblyName = null;
  2176. System.Reflection.Assembly assembly = null;
  2177. WeakReference wref = (WeakReference)Node.VisitorTypeFor[customVisitorClassName];
  2178. Type visitorType = wref == null ? null : (System.Type)wref.Target;
  2179. if (visitorType == typeof(object)) return null;
  2180. string callerDirectory = null;
  2181. if (visitorType == null){
  2182. assembly = nodeType.Assembly;
  2183. if (assembly == null) return null;
  2184. visitorType = assembly.GetType(customVisitorClassName, false);
  2185. }
  2186. if (visitorType == null) {
  2187. //^ assert assembly != null;
  2188. if (assembly.Location == null) return null;
  2189. callerDirectory = Path.GetDirectoryName(assembly.Location);
  2190. visitorAssemblyName = new System.Reflection.AssemblyName();
  2191. visitorAssemblyName.Name = "Visitors";
  2192. visitorAssemblyName.CodeBase = "file:///" + Path.Combine(callerDirectory, "Visitors.dll");
  2193. try {
  2194. assembly = System.Reflection.Assembly.Load(visitorAssemblyName);
  2195. } catch { }
  2196. if (assembly != null)
  2197. visitorType = assembly.GetType(customVisitorClassName, false);
  2198. if (visitorType == null) {
  2199. visitorAssemblyName.Name = customVisitorClassName;
  2200. visitorAssemblyName.CodeBase = "file:///" + Path.Combine(callerDirectory, customVisitorClassName+".dll");
  2201. try {
  2202. assembly = System.Reflection.Assembly.Load(visitorAssemblyName);
  2203. } catch { }
  2204. if (assembly != null)
  2205. visitorType = assembly.GetType(customVisitorClassName, false);
  2206. }
  2207. }
  2208. if (visitorType == null){
  2209. //Put fake entry into hashtable to short circuit future lookups
  2210. visitorType = typeof(object);
  2211. assembly = nodeType.Assembly;
  2212. }
  2213. if (assembly != null){ //Only happens if there was a cache miss
  2214. lock(Node.VisitorTypeFor){
  2215. Node.VisitorTypeFor[customVisitorClassName] = new WeakReference(visitorType);
  2216. }
  2217. }
  2218. if (visitorType == typeof(object)) return null;
  2219. try{
  2220. return System.Activator.CreateInstance(visitorType, new object[]{callingVisitor});
  2221. }catch{}
  2222. return null;
  2223. }
  2224. #endif
  2225. int IUniqueKey.UniqueId { get { return this.UniqueKey; } }
  2226. #if MinimalReader
  2227. // Return a constant value for IsNormalized in the binary-only
  2228. // reader. This results in less code churn elsewhere.
  2229. internal bool IsNormalized{get{return true;}}
  2230. #endif
  2231. }
  2232. #if !MinimalReader
  2233. public abstract class ErrorNode : Node{
  2234. public int Code;
  2235. #if ExtendedRuntime
  2236. public bool DoNotSuppress;
  2237. #endif
  2238. public string[] MessageParameters;
  2239. protected ErrorNode(int code, params string[] messageParameters)
  2240. : base(NodeType.Undefined){
  2241. this.Code = code;
  2242. this.MessageParameters = messageParameters;
  2243. }
  2244. public virtual string GetErrorNumber(){
  2245. return this.Code.ToString("0000");
  2246. }
  2247. public string GetMessage(){
  2248. return this.GetMessage(null);
  2249. }
  2250. #if ExtendedRuntime
  2251. [return: Microsoft.Contracts.NotNull]
  2252. #endif
  2253. public abstract string GetMessage(System.Globalization.CultureInfo culture);
  2254. public virtual string GetMessage(string key, System.Resources.ResourceManager rm, System.Globalization.CultureInfo culture){
  2255. if (rm == null || key == null) return null;
  2256. string localizedString = rm.GetString(key, culture);
  2257. if (localizedString == null) localizedString = key;
  2258. string[] messageParameters = this.MessageParameters;
  2259. if (messageParameters == null || messageParameters.Length == 0) return localizedString;
  2260. return string.Format(localizedString, messageParameters);
  2261. }
  2262. public abstract int Severity{
  2263. get;
  2264. }
  2265. public static int GetCountAtSeverity(ErrorNodeList errors, int minSeverity, int maxSeverity){
  2266. if (errors == null) return 0;
  2267. int n = 0;
  2268. for (int i = 0; i < errors.Count; i++){
  2269. ErrorNode e = errors[i];
  2270. if (e == null)
  2271. continue;
  2272. int s = e.Severity;
  2273. if (minSeverity <= s && s <= maxSeverity)
  2274. n++;
  2275. }
  2276. return n;
  2277. }
  2278. }
  2279. public class Expose : Statement{
  2280. public Expression Instance;
  2281. public Block Body;
  2282. public bool IsLocal;
  2283. public Expose(NodeType nodeType)
  2284. : base(nodeType){
  2285. }
  2286. }
  2287. public class Acquire : Statement{
  2288. public bool ReadOnly;
  2289. public Statement Target;
  2290. public Expression Condition;
  2291. public Expression ConditionFunction;
  2292. public Block Body;
  2293. public BlockScope ScopeForTemporaryVariable;
  2294. public Acquire() : base(NodeType.Acquire) {
  2295. }
  2296. }
  2297. #endif
  2298. public class Expression : Node{
  2299. private TypeNode type;
  2300. #if FxCop
  2301. internal int ILOffset;
  2302. #endif
  2303. #if !FxCop && ILOFFSETS
  2304. public int ILOffset;
  2305. #endif
  2306. public Expression(NodeType nodeType)
  2307. : base(nodeType){
  2308. }
  2309. public Expression(NodeType nodeType, TypeNode type)
  2310. : base(nodeType){
  2311. this.type = type;
  2312. }
  2313. public virtual TypeNode Type{
  2314. get{return this.type;}
  2315. set{this.type = value;}
  2316. }
  2317. }
  2318. #if !MinimalReader
  2319. public class ExpressionSnippet : Expression{
  2320. public IParserFactory ParserFactory;
  2321. public ExpressionSnippet()
  2322. : base(NodeType.ExpressionSnippet){
  2323. }
  2324. public ExpressionSnippet(IParserFactory parserFactory, SourceContext sctx)
  2325. : base(NodeType.ExpressionSnippet){
  2326. this.ParserFactory = parserFactory;
  2327. this.SourceContext = sctx;
  2328. }
  2329. }
  2330. #endif
  2331. public class MemberBinding : Expression{
  2332. private int alignment;
  2333. private Member boundMember;
  2334. #if !MinimalReader
  2335. public Expression BoundMemberExpression;
  2336. #endif
  2337. private Expression targetObject;
  2338. private bool @volatile;
  2339. public MemberBinding()
  2340. : base(NodeType.MemberBinding){
  2341. }
  2342. public MemberBinding(Expression targetObject, Member/*!*/ boundMember)
  2343. : this(targetObject, boundMember, false, -1){
  2344. if (boundMember is Field) this.Volatile = ((Field)boundMember).IsVolatile;
  2345. }
  2346. #if !MinimalReader
  2347. public MemberBinding(Expression targetObject, Member/*!*/ boundMember, Expression boundMemberExpression)
  2348. : this(targetObject, boundMember, false, -1){
  2349. if (boundMember is Field) this.Volatile = ((Field)boundMember).IsVolatile;
  2350. this.BoundMemberExpression = boundMemberExpression;
  2351. }
  2352. public MemberBinding(Expression targetObject, Member/*!*/ boundMember, SourceContext sctx)
  2353. : this(targetObject, boundMember, false, -1){
  2354. if (boundMember is Field) this.Volatile = ((Field)boundMember).IsVolatile;
  2355. this.SourceContext = sctx;
  2356. }
  2357. public MemberBinding(Expression targetObject, Member/*!*/ boundMember, SourceContext sctx, Expression boundMemberExpression)
  2358. : this(targetObject, boundMember, false, -1){
  2359. if (boundMember is Field) this.Volatile = ((Field)boundMember).IsVolatile;
  2360. this.SourceContext = sctx;
  2361. this.BoundMemberExpression = boundMemberExpression;
  2362. }
  2363. #endif
  2364. public MemberBinding(Expression targetObject, Member/*!*/ boundMember, bool @volatile, int alignment)
  2365. : base(NodeType.MemberBinding){
  2366. Debug.Assert(boundMember != null);
  2367. this.alignment = alignment;
  2368. this.boundMember = boundMember;
  2369. this.targetObject = targetObject;
  2370. this.@volatile = @volatile;
  2371. switch(boundMember.NodeType){
  2372. case NodeType.Field : this.Type = ((Field)boundMember).Type; break;
  2373. case NodeType.Method : this.Type = ((Method)boundMember).ReturnType; break;
  2374. case NodeType.Event : this.Type = ((Event)boundMember).HandlerType; break;
  2375. default : this.Type = boundMember as TypeNode; break;
  2376. }
  2377. }
  2378. public int Alignment{
  2379. get{return this.alignment;}
  2380. set{this.alignment = value;}
  2381. }
  2382. public Member BoundMember{
  2383. get{return this.boundMember;}
  2384. set{this.boundMember = value;}
  2385. }
  2386. public Expression TargetObject{
  2387. get{return this.targetObject;}
  2388. set{this.targetObject = value;}
  2389. }
  2390. public bool Volatile{
  2391. get{return this.@volatile;}
  2392. set{this.@volatile = value;}
  2393. }
  2394. }
  2395. public class AddressDereference : Expression{
  2396. private Expression address;
  2397. private int alignment;
  2398. private bool isVolatile;
  2399. #if !MinimalReader
  2400. public enum ExplicitOp { None=0, Star, Arrow }
  2401. private ExplicitOp explicitOperation; // was explicit in source (* or ->)
  2402. #endif
  2403. public AddressDereference()
  2404. : base(NodeType.AddressDereference){
  2405. }
  2406. public AddressDereference(Expression address, TypeNode type)
  2407. : this(address, type, false, -1){
  2408. }
  2409. #if !MinimalReader
  2410. public AddressDereference(Expression address, TypeNode type, SourceContext sctx)
  2411. : this(address, type, false, -1, sctx){
  2412. }
  2413. #endif
  2414. public AddressDereference(Expression address, TypeNode type, bool isVolatile, int alignment)
  2415. : base(NodeType.AddressDereference){
  2416. this.address = address;
  2417. this.alignment = alignment;
  2418. this.Type = type;
  2419. this.isVolatile = isVolatile;
  2420. }
  2421. #if !MinimalReader
  2422. public AddressDereference(Expression address, TypeNode type, bool Volatile, int alignment, SourceContext sctx)
  2423. : base(NodeType.AddressDereference){
  2424. this.address = address;
  2425. this.alignment = alignment;
  2426. this.Type = type;
  2427. this.isVolatile = Volatile;
  2428. this.SourceContext = sctx;
  2429. }
  2430. #endif
  2431. public Expression Address{
  2432. get{return this.address;}
  2433. set{this.address = value;}
  2434. }
  2435. public int Alignment{
  2436. get{return this.alignment;}
  2437. set{this.alignment = value;}
  2438. }
  2439. public bool Volatile{
  2440. get{return this.isVolatile;}
  2441. set{this.isVolatile = value;}
  2442. }
  2443. #if !MinimalReader
  2444. public bool Explicit{
  2445. get{return this.explicitOperation != ExplicitOp.None;}
  2446. }
  2447. public ExplicitOp ExplicitOperator {
  2448. get { return this.explicitOperation; }
  2449. set { this.explicitOperation = value; }
  2450. }
  2451. #endif
  2452. }
  2453. public class UnaryExpression : Expression{
  2454. private Expression operand;
  2455. public UnaryExpression()
  2456. : base(NodeType.Nop){
  2457. }
  2458. public UnaryExpression(Expression operand, NodeType nodeType)
  2459. : base(nodeType){
  2460. this.Operand = operand;
  2461. }
  2462. #if !MinimalReader
  2463. public UnaryExpression(Expression operand, NodeType nodeType, SourceContext sctx)
  2464. : base(nodeType){
  2465. this.operand = operand;
  2466. this.SourceContext = sctx;
  2467. }
  2468. #endif
  2469. public UnaryExpression(Expression operand, NodeType nodeType, TypeNode type)
  2470. : base(nodeType){
  2471. this.operand = operand;
  2472. this.Type = type;
  2473. }
  2474. #if !MinimalReader
  2475. public UnaryExpression(Expression operand, NodeType nodeType, TypeNode type, SourceContext sctx)
  2476. : base(nodeType){
  2477. this.operand = operand;
  2478. this.Type = type;
  2479. this.SourceContext = sctx;
  2480. }
  2481. #endif
  2482. public Expression Operand{
  2483. get{return this.operand;}
  2484. set{this.operand = value;}
  2485. }
  2486. }
  2487. #if !MinimalReader
  2488. public class PrefixExpression : Expression{
  2489. public Expression Expression;
  2490. public NodeType Operator;
  2491. public Method OperatorOverload;
  2492. public PrefixExpression()
  2493. : base(NodeType.PrefixExpression){
  2494. }
  2495. public PrefixExpression(Expression expression, NodeType Operator, SourceContext sourceContext)
  2496. : base(NodeType.PrefixExpression){
  2497. this.Expression = expression;
  2498. this.Operator = Operator;
  2499. this.SourceContext = sourceContext;
  2500. }
  2501. }
  2502. public class PostfixExpression : Expression{
  2503. public Expression Expression;
  2504. public NodeType Operator;
  2505. public Method OperatorOverload;
  2506. public PostfixExpression()
  2507. : base(NodeType.PostfixExpression){
  2508. }
  2509. public PostfixExpression(Expression expression, NodeType Operator, SourceContext sourceContext)
  2510. : base(NodeType.PostfixExpression){
  2511. this.Expression = expression;
  2512. this.Operator = Operator;
  2513. this.SourceContext = sourceContext;
  2514. }
  2515. }
  2516. #endif
  2517. public class BinaryExpression : Expression{
  2518. private Expression operand1;
  2519. private Expression operand2;
  2520. public BinaryExpression()
  2521. : base(NodeType.Nop){
  2522. }
  2523. public BinaryExpression(Expression operand1, Expression operand2, NodeType nodeType)
  2524. : base(nodeType){
  2525. this.operand1 = operand1;
  2526. this.operand2 = operand2;
  2527. }
  2528. public BinaryExpression(Expression operand1, Expression operand2, NodeType nodeType, TypeNode resultType)
  2529. : base(nodeType){
  2530. this.operand1 = operand1;
  2531. this.operand2 = operand2;
  2532. this.Type = resultType;
  2533. }
  2534. #if !MinimalReader
  2535. public BinaryExpression(Expression operand1, Expression operand2, NodeType nodeType, SourceContext ctx)
  2536. : base(nodeType){
  2537. this.operand1 = operand1;
  2538. this.operand2 = operand2;
  2539. this.SourceContext = ctx;
  2540. }
  2541. public BinaryExpression(Expression operand1, Expression operand2, NodeType nodeType, TypeNode resultType, SourceContext ctx)
  2542. : base(nodeType){
  2543. this.operand1 = operand1;
  2544. this.operand2 = operand2;
  2545. this.Type = resultType;
  2546. this.SourceContext = ctx;
  2547. }
  2548. #endif
  2549. public Expression Operand1{
  2550. get{return this.operand1;}
  2551. set{this.operand1 = value;}
  2552. }
  2553. public Expression Operand2{
  2554. get{return this.operand2;}
  2555. set{this.operand2 = value;}
  2556. }
  2557. }
  2558. public class TernaryExpression : Expression{
  2559. private Expression operand1;
  2560. private Expression operand2;
  2561. private Expression operand3;
  2562. public TernaryExpression()
  2563. : base(NodeType.Nop){
  2564. }
  2565. public TernaryExpression(Expression operand1, Expression operand2, Expression operand3, NodeType nodeType, TypeNode resultType)
  2566. : base(nodeType){
  2567. this.operand1 = operand1;
  2568. this.operand2 = operand2;
  2569. this.operand3 = operand3;
  2570. this.Type = resultType;
  2571. }
  2572. public Expression Operand1{
  2573. get{return this.operand1;}
  2574. set{this.operand1 = value;}
  2575. }
  2576. public Expression Operand2{
  2577. get{return this.operand2;}
  2578. set{this.operand2 = value;}
  2579. }
  2580. public Expression Operand3{
  2581. get{return this.operand3;}
  2582. set{this.operand3 = value;}
  2583. }
  2584. }
  2585. public abstract class NaryExpression : Expression{
  2586. #if !FxCop
  2587. public ExpressionList Operands;
  2588. #else
  2589. private ExpressionList operands;
  2590. public ExpressionList Operands {
  2591. get {return this.operands;}
  2592. internal set{this.operands = value;}
  2593. }
  2594. #endif
  2595. protected NaryExpression()
  2596. : base(NodeType.Nop){
  2597. }
  2598. protected NaryExpression(ExpressionList operands, NodeType nodeType)
  2599. : base(nodeType){
  2600. this.Operands = operands;
  2601. }
  2602. }
  2603. #if !MinimalReader
  2604. public class ApplyToAll : BinaryExpression{
  2605. public Local ElementLocal;
  2606. public Method ResultIterator;
  2607. public ApplyToAll()
  2608. : base(null, null, NodeType.ApplyToAll){
  2609. }
  2610. public ApplyToAll(Expression operand1, Expression operand2)
  2611. : base(operand1, operand2, NodeType.ApplyToAll){
  2612. }
  2613. public ApplyToAll(Expression operand1, Expression operand2, SourceContext ctx)
  2614. : base(operand1, operand2, NodeType.ApplyToAll){
  2615. this.SourceContext = ctx;
  2616. }
  2617. }
  2618. #endif
  2619. public class NamedArgument : Expression{
  2620. private bool isCustomAttributeProperty;
  2621. private Identifier name;
  2622. private Expression value;
  2623. private bool valueIsBoxed;
  2624. public NamedArgument()
  2625. : base(NodeType.NamedArgument){
  2626. }
  2627. public NamedArgument(Identifier name, Expression value)
  2628. : base(NodeType.NamedArgument){
  2629. this.Name = name;
  2630. this.Value = value;
  2631. }
  2632. #if !MinimalReader
  2633. public NamedArgument(Identifier name, Expression value, SourceContext ctx)
  2634. : base(NodeType.NamedArgument){
  2635. this.Name = name;
  2636. this.Value = value;
  2637. this.SourceContext = ctx;
  2638. }
  2639. #endif
  2640. public bool IsCustomAttributeProperty{ //TODO: rename this to IsProperty
  2641. get{return this.isCustomAttributeProperty;}
  2642. set{this.isCustomAttributeProperty = value;}
  2643. }
  2644. public Identifier Name{
  2645. get{return this.name;}
  2646. set{this.name = value;}
  2647. }
  2648. public Expression Value{
  2649. get{return this.value;}
  2650. set{this.value = value;}
  2651. }
  2652. public bool ValueIsBoxed{
  2653. get{return this.valueIsBoxed;}
  2654. set{this.valueIsBoxed = value;}
  2655. }
  2656. }
  2657. /// <summary>
  2658. /// This an Expression wrapper for compile time constants. It is assumed to be correct by construction.
  2659. /// In Normalized IR, the wrapped value must be a primitive numeric type or an enum or a string or null.
  2660. /// If used in custom attributes, types are also allowed as well as single dimensional arrays of other allowed types.
  2661. /// If the wrapped value is null, any reference type is allowed, except in custom attributes, where it must be Type or String.
  2662. /// </summary>
  2663. public class Literal : Expression{
  2664. private object value;
  2665. #if !MinimalReader
  2666. public bool TypeWasExplicitlySpecifiedInSource;
  2667. public Expression SourceExpression;
  2668. #endif
  2669. public Literal()
  2670. : base(NodeType.Literal){
  2671. }
  2672. #if !NoReflection
  2673. public Literal(object Value)
  2674. : base(NodeType.Literal){
  2675. this.value = Value;
  2676. }
  2677. #endif
  2678. public Literal(object value, TypeNode type)
  2679. : base(NodeType.Literal){
  2680. this.value = value;
  2681. this.Type = type;
  2682. }
  2683. public Literal(object value, TypeNode type, SourceContext sourceContext)
  2684. : base(NodeType.Literal){
  2685. this.value = value;
  2686. this.SourceContext = sourceContext;
  2687. this.Type = type;
  2688. }
  2689. /// <summary>
  2690. /// Holds the wrapped compile time constant value.
  2691. /// </summary>
  2692. public object Value{
  2693. get{return this.value;}
  2694. }
  2695. public override string ToString(){
  2696. if (this.Value == null) return "Literal for null";
  2697. return this.Value.ToString();
  2698. }
  2699. #if !NoWriter
  2700. public static bool IsNullLiteral(Expression expr){
  2701. Literal lit = expr as Literal;
  2702. if (lit == null) return false;
  2703. if (lit.Type != CoreSystemTypes.Object || lit.Value != null) return false;
  2704. return true;
  2705. }
  2706. //TODO: replace these with properties that freshly allocate them. It appears that Literals sometimes get clobbered.
  2707. public static Literal DoubleOne;
  2708. public static Literal False;
  2709. public static Literal Int32MinusOne;
  2710. public static Literal Int32Zero;
  2711. public static Literal Int32One;
  2712. public static Literal Int32Two;
  2713. public static Literal Int32Sixteen;
  2714. public static Literal Int64Zero;
  2715. public static Literal Int64One;
  2716. public static Literal Null;
  2717. public static Literal SingleOne;
  2718. public static Literal True;
  2719. public static void Initialize(){
  2720. Literal.DoubleOne = new Literal(1.0, CoreSystemTypes.Double);
  2721. Literal.False = new Literal(false, CoreSystemTypes.Boolean);
  2722. Literal.Int32MinusOne = new Literal(-1, CoreSystemTypes.Int32);
  2723. Literal.Int32Zero = new Literal(0, CoreSystemTypes.Int32);
  2724. Literal.Int32One = new Literal(1, CoreSystemTypes.Int32);
  2725. Literal.Int32Two = new Literal(2, CoreSystemTypes.Int32);
  2726. Literal.Int32Sixteen = new Literal(16, CoreSystemTypes.Int32);
  2727. Literal.Int64Zero = new Literal(0L, CoreSystemTypes.Int64);
  2728. Literal.Int64One = new Literal(1L, CoreSystemTypes.Int64);
  2729. Literal.Null = new Literal(null, CoreSystemTypes.Object);
  2730. Literal.SingleOne = new Literal(1.0f, CoreSystemTypes.Single);
  2731. Literal.True = new Literal(true, CoreSystemTypes.Boolean);
  2732. }
  2733. public static void ClearStatics(){
  2734. Literal.DoubleOne = null;
  2735. Literal.False = null;
  2736. Literal.Int32MinusOne = null;
  2737. Literal.Int32Zero = null;
  2738. Literal.Int32One = null;
  2739. Literal.Int32Two = null;
  2740. Literal.Int32Sixteen = null;
  2741. Literal.Int64Zero = null;
  2742. Literal.Int64One = null;
  2743. Literal.Null = null;
  2744. Literal.SingleOne = null;
  2745. Literal.True = null;
  2746. }
  2747. #endif
  2748. }
  2749. public class This : Parameter{
  2750. public This(){
  2751. this.NodeType = NodeType.This;
  2752. this.Name = StandardIds.This;
  2753. }
  2754. public This(TypeNode type){
  2755. this.NodeType = NodeType.This;
  2756. this.Name = StandardIds.This;
  2757. this.Type = type;
  2758. }
  2759. #if !MinimalReader
  2760. public bool IsCtorCall = false;
  2761. public This(SourceContext sctx, bool isCtorCall){
  2762. this.NodeType = NodeType.This;
  2763. this.Name = StandardIds.This;
  2764. this.SourceContext = sctx;
  2765. this.IsCtorCall = isCtorCall;
  2766. }
  2767. public This(TypeNode type, SourceContext sctx){
  2768. this.NodeType = NodeType.This;
  2769. this.Name = StandardIds.This;
  2770. this.Type = type;
  2771. this.SourceContext = sctx;
  2772. }
  2773. public override bool Equals(object obj) {
  2774. ThisBinding binding = obj as ThisBinding;
  2775. return obj == this || binding != null && binding.BoundThis == this;
  2776. }
  2777. public override int GetHashCode(){
  2778. return base.GetHashCode();
  2779. }
  2780. #endif
  2781. #if ExtendedRuntime
  2782. public override bool IsUniversallyDelayed {
  2783. get {
  2784. if (this.DeclaringMethod is InstanceInitializer && this.DeclaringMethod.DeclaringType != null &&
  2785. !this.DeclaringMethod.DeclaringType.IsValueType) {
  2786. // by default, class constructors should be delayed
  2787. return !(this.DeclaringMethod.GetAttribute(ExtendedRuntimeTypes.NotDelayedAttribute) != null);
  2788. }
  2789. return (this.DeclaringMethod.GetAttribute(ExtendedRuntimeTypes.DelayedAttribute) != null);
  2790. }
  2791. }
  2792. #endif
  2793. }
  2794. #if !MinimalReader
  2795. public class ThisBinding : This, IUniqueKey{
  2796. public This/*!*/ BoundThis;
  2797. public ThisBinding(This/*!*/ boundThis, SourceContext sctx) {
  2798. if (boundThis == null) throw new ArgumentNullException("boundThis");
  2799. this.BoundThis = boundThis;
  2800. this.SourceContext = sctx;
  2801. this.Type = boundThis.Type;
  2802. this.Name = boundThis.Name;
  2803. this.TypeExpression = boundThis.TypeExpression;
  2804. this.Attributes = boundThis.Attributes;
  2805. this.DefaultValue = boundThis.DefaultValue;
  2806. this.Flags = boundThis.Flags;
  2807. this.MarshallingInformation = boundThis.MarshallingInformation;
  2808. this.DeclaringMethod = boundThis.DeclaringMethod;
  2809. this.ParameterListIndex = boundThis.ParameterListIndex;
  2810. this.ArgumentListIndex = boundThis.ArgumentListIndex;
  2811. //^ base();
  2812. }
  2813. public override int GetHashCode(){
  2814. return this.BoundThis.GetHashCode();
  2815. }
  2816. public override bool Equals(object obj){
  2817. ThisBinding pb = obj as ThisBinding;
  2818. if (pb != null)
  2819. return this.BoundThis.Equals(pb.BoundThis);
  2820. else
  2821. return this.BoundThis.Equals(obj);
  2822. }
  2823. int IUniqueKey.UniqueId{
  2824. get {return this.BoundThis.UniqueKey;}
  2825. }
  2826. /// <summary>
  2827. /// Must forward type to underlying binding, since ThisBindings get built at times when
  2828. /// the bound This node does not have its final type yet.
  2829. /// </summary>
  2830. public override TypeNode Type {
  2831. get {
  2832. return BoundThis.Type;
  2833. }
  2834. set {
  2835. BoundThis.Type = value;
  2836. }
  2837. }
  2838. }
  2839. public class Base : Expression{
  2840. /// <summary>
  2841. /// When the source uses the C# compatibility mode, base calls cannot be put after non-null
  2842. /// field initialization, but must be put before the body. But the user can specify where
  2843. /// the base ctor call should be performed by using "base;" as a marker. During parsing
  2844. /// this flag is set so the right code transformations can be performed at code generation.
  2845. /// </summary>
  2846. public bool UsedAsMarker;
  2847. public bool IsCtorCall = false;
  2848. public Base()
  2849. : base(NodeType.Base){
  2850. }
  2851. public Base(SourceContext sctx, bool isCtorCall)
  2852. : base(NodeType.Base){
  2853. this.SourceContext = sctx;
  2854. this.IsCtorCall = isCtorCall;
  2855. }
  2856. }
  2857. public class ImplicitThis : Expression{
  2858. public int LexLevel;
  2859. public Class MostNestedScope;
  2860. public ImplicitThis()
  2861. : base(NodeType.ImplicitThis){
  2862. }
  2863. public ImplicitThis(Class mostNestedScope, int lexLevel)
  2864. : base(NodeType.ImplicitThis){
  2865. this.LexLevel = lexLevel;
  2866. this.MostNestedScope = mostNestedScope;
  2867. }
  2868. }
  2869. public class CurrentClosure : Expression{
  2870. public Method Method;
  2871. public CurrentClosure()
  2872. : base(NodeType.CurrentClosure){
  2873. }
  2874. public CurrentClosure(Method method, TypeNode type)
  2875. : base(NodeType.CurrentClosure){
  2876. this.Method = method;
  2877. this.Type = type;
  2878. }
  2879. public CurrentClosure(Method method, TypeNode type, SourceContext sctx)
  2880. : base(NodeType.CurrentClosure){
  2881. this.Method = method;
  2882. this.Type = type;
  2883. this.SourceContext = sctx;
  2884. }
  2885. }
  2886. public class SetterValue : Expression{
  2887. public SetterValue()
  2888. : base(NodeType.SetterValue){
  2889. }
  2890. }
  2891. #endif
  2892. public class Identifier : Expression{
  2893. private int hashCode;
  2894. internal int length;
  2895. private string name;
  2896. private int offset;
  2897. #if !FxCop
  2898. private DocumentText text;
  2899. #endif
  2900. #if !MinimalReader
  2901. public Identifier Prefix;
  2902. #endif
  2903. /// <summary>An identifier with the empty string ("") as its value.</summary>
  2904. public static readonly Identifier/*!*/ Empty = new Identifier("");
  2905. #if !FxCop
  2906. private Identifier(DocumentText/*!*/ text, int offset, int length)
  2907. : base(NodeType.Identifier){
  2908. this.text = text;
  2909. this.offset = offset;
  2910. this.length = length;
  2911. ulong hcode = 0;
  2912. for (int i = offset, n = length+i; i < n; i++){
  2913. char ch = text[i];
  2914. hcode = hcode*17 + ch;
  2915. }
  2916. this.hashCode = ((int)hcode) & int.MaxValue;
  2917. }
  2918. public static Identifier/*!*/ For(SourceContext sctx) {
  2919. DocumentText text = null;
  2920. if (sctx.Document != null) text = sctx.Document.Text;
  2921. if (text == null) text = new DocumentText("");
  2922. Identifier id = new Identifier(text, sctx.StartPos, sctx.EndPos-sctx.StartPos);
  2923. id.SourceContext = sctx;
  2924. return id;
  2925. }
  2926. #endif
  2927. public Identifier(string name)
  2928. : base(NodeType.Identifier){
  2929. if (name == null) name = "";
  2930. this.name = name;
  2931. int n = this.length = name.Length;
  2932. ulong hcode = 0;
  2933. for (int i = 0; i < n; i++){
  2934. char ch = name[i];
  2935. hcode = hcode*17 + ch;
  2936. }
  2937. this.hashCode = ((int)hcode) & int.MaxValue;
  2938. }
  2939. #if !MinimalReader
  2940. public Identifier(string name, SourceContext sctx)
  2941. : this(name){
  2942. this.SourceContext = sctx;
  2943. }
  2944. #endif
  2945. public static Identifier/*!*/ For(string/*!*/ name) {
  2946. return new Identifier(name);
  2947. }
  2948. private unsafe Identifier(byte* pointer, int offset)
  2949. : base(NodeType.Identifier){
  2950. this.offset = offset;
  2951. bool isASCII = true;
  2952. int length = 0;
  2953. ulong hcode = 0;
  2954. for (int i = offset; ; i++){
  2955. byte b = *(pointer+i);
  2956. if (b == 0) break;
  2957. if ((b & 0x80) != 0) isASCII = false;
  2958. hcode = hcode*17 + b;
  2959. length++;
  2960. }
  2961. if (isASCII){
  2962. this.hashCode = ((int)hcode) & int.MaxValue;
  2963. this.length = length;
  2964. this.name = new string((sbyte*)pointer, offset, length, Encoding.ASCII);
  2965. return;
  2966. }
  2967. hcode = 0;
  2968. string name = this.name = new string((sbyte*)pointer, offset, length, Encoding.UTF8);
  2969. for (int i = 0, n = this.length = name.Length; i < n; i++){
  2970. char ch = name[i];
  2971. hcode = hcode*17 + ch;
  2972. }
  2973. this.hashCode = ((int)hcode) & int.MaxValue;
  2974. }
  2975. /// <summary>
  2976. /// Use when pointer+offset points to a null terminated string of UTF8 code points.
  2977. /// </summary>
  2978. internal unsafe static Identifier/*!*/ For(byte* pointer, int offset) {
  2979. //TODO: first look for identifier in cache
  2980. return new Identifier(pointer, offset);
  2981. }
  2982. private unsafe Identifier(byte* pointer, uint length)
  2983. : base(NodeType.Identifier){
  2984. //this.offset = 0;
  2985. this.length = (int)length;
  2986. ulong hcode = 0;
  2987. for (uint i = 0; i < length; i++){
  2988. byte b = *(pointer+i);
  2989. if ((b & 0x80) != 0) goto doUTF8decoding;
  2990. hcode = hcode*17 + b;
  2991. }
  2992. this.hashCode = ((int)hcode) & int.MaxValue;
  2993. this.name = new string((sbyte*)pointer, 0, this.length, Encoding.ASCII);
  2994. return;
  2995. doUTF8decoding:
  2996. string name = this.name = new string((sbyte*)pointer, 0, this.length, Encoding.UTF8);
  2997. for (int i = 0, n = this.length = name.Length; i < n; i++){
  2998. char ch = name[i];
  2999. hcode = hcode*17 + ch;
  3000. }
  3001. this.hashCode = ((int)hcode) & int.MaxValue;
  3002. }
  3003. /// <summary>
  3004. /// Use when pointer points to a string of UTF8 code points of a given length
  3005. /// </summary>
  3006. internal unsafe static Identifier/*!*/ For(byte* pointer, uint length) {
  3007. //TODO: first look for identifier in cache
  3008. return new Identifier(pointer, length);
  3009. }
  3010. private static readonly object/*!*/ Lock = new object();
  3011. private struct CanonicalIdentifier{
  3012. internal string/*!*/ Name;
  3013. internal int UniqueIdKey;
  3014. internal int HashCode;
  3015. internal CanonicalIdentifier(string/*!*/ name, int uniqueIdKey, int hashCode) {
  3016. this.Name = name;
  3017. this.UniqueIdKey = uniqueIdKey;
  3018. this.HashCode = hashCode;
  3019. }
  3020. }
  3021. private static CanonicalIdentifier[]/*!*/ HashTable = new CanonicalIdentifier[16*1024];
  3022. private static int count;
  3023. private int GetUniqueIdKey(){
  3024. lock(Identifier.Lock){
  3025. int hcode = this.hashCode;
  3026. CanonicalIdentifier[] hTable = Identifier.HashTable;
  3027. int length = hTable.Length;
  3028. int i = hcode % length;
  3029. CanonicalIdentifier id = hTable[i];
  3030. while (id.Name != null){
  3031. if (this.HasSameNameAs(id)) return id.UniqueIdKey;
  3032. i = (i+1) % length;
  3033. id = hTable[i];
  3034. }
  3035. int count = Identifier.count;
  3036. int countp1 = count+1;
  3037. Identifier.count = countp1;
  3038. string name = this.Name; //Get a local copy of the name and drop any reference to a DocumentText instance
  3039. hTable[i] = new CanonicalIdentifier(name, countp1, hcode);
  3040. if (countp1 > length/2) Rehash(); //Threshold exceeded, need to rehash
  3041. return countp1;
  3042. }
  3043. }
  3044. private unsafe bool HasSameNameAs(CanonicalIdentifier id) {
  3045. int myLength = this.length;
  3046. int idLength = id.Name.Length;
  3047. if (myLength != idLength) return false;
  3048. string myName = this.name;
  3049. string idName = id.Name;
  3050. #if !FxCop
  3051. if (myName == null){
  3052. int myOffset = this.offset;
  3053. if (this.text != null && this.text.Equals(idName, myOffset, myLength)){
  3054. this.name = idName;
  3055. this.text = null;
  3056. return true;
  3057. }
  3058. return false;
  3059. }
  3060. #endif
  3061. return myName == idName;
  3062. }
  3063. public string/*!*/ Name{ //TODO: need a better name for this property
  3064. get{
  3065. #if !FxCop
  3066. if (this.name != null) return this.name;
  3067. lock(this){
  3068. if (this.name != null) return this.name;
  3069. //^ assume this.text != null;
  3070. int length = this.length;
  3071. int offset = this.offset;
  3072. this.name = this.text.Substring(offset, length);
  3073. this.text = null;
  3074. return this.name;
  3075. }
  3076. #else
  3077. return this.name;
  3078. #endif
  3079. }
  3080. }
  3081. private static void Rehash(){
  3082. CanonicalIdentifier[] hTable = Identifier.HashTable;
  3083. int n = hTable.Length;
  3084. int n2 = n*2;
  3085. CanonicalIdentifier[] newhTable = new CanonicalIdentifier[n2];
  3086. for (int i = 0; i < n; i++){
  3087. CanonicalIdentifier id = hTable[i];
  3088. if (id.Name == null) continue;
  3089. int j = id.HashCode % n2;
  3090. CanonicalIdentifier id2 = newhTable[j];
  3091. while (id2.Name != null){
  3092. j = (j+1) % n2;
  3093. id2 = newhTable[j];
  3094. }
  3095. newhTable[j] = id;
  3096. }
  3097. Identifier.HashTable = newhTable;
  3098. }
  3099. public override string/*!*/ ToString(){
  3100. #if !MinimalReader
  3101. if (this.Prefix != null)
  3102. return this.Prefix.Name+":"+this.Name;
  3103. #endif
  3104. if (this.Name == null) return "";
  3105. return this.Name;
  3106. }
  3107. private int uniqueIdKey;
  3108. /// <summary>
  3109. /// Returns an integer that is the same for every Identifier instance that has the same string value, and that is different from
  3110. /// every other identifier instance that has a different string value. Useful for efficient equality tests when hashing identifiers.
  3111. /// </summary>
  3112. public int UniqueIdKey{
  3113. get{
  3114. int result = this.uniqueIdKey;
  3115. if (result != 0) return result;
  3116. return this.uniqueIdKey = this.GetUniqueIdKey();
  3117. }
  3118. }
  3119. [Obsolete("Use Identifier.UniqueIdKey instead")]
  3120. public new int UniqueKey{
  3121. get{
  3122. int result = this.uniqueIdKey;
  3123. if (result != 0) return result;
  3124. return this.uniqueIdKey = this.GetUniqueIdKey();
  3125. }
  3126. }
  3127. }
  3128. #if !MinimalReader
  3129. public class QualifiedIdentifier : Expression{
  3130. public Identifier Identifier;
  3131. public Expression Qualifier;
  3132. public Expression BoundMember;
  3133. public bool QualifierIsNamespace;
  3134. public QualifiedIdentifier()
  3135. : base(NodeType.QualifiedIdentifer){
  3136. }
  3137. public QualifiedIdentifier(Expression qualifier, Identifier identifier)
  3138. : base(NodeType.QualifiedIdentifer){
  3139. this.Identifier = identifier;
  3140. this.Qualifier = qualifier;
  3141. }
  3142. public QualifiedIdentifier(Expression qualifier, Identifier identifier, SourceContext sourceContext)
  3143. : base(NodeType.QualifiedIdentifer){
  3144. this.Identifier = identifier;
  3145. this.Qualifier = qualifier;
  3146. this.SourceContext = sourceContext;
  3147. }
  3148. public QualifiedIdentifier(Expression qualifier, Identifier identifier, SourceContext sourceContext, bool qualifierIsNamespace)
  3149. : base(NodeType.QualifiedIdentifer){
  3150. this.Identifier = identifier;
  3151. this.Qualifier = qualifier;
  3152. this.SourceContext = sourceContext;
  3153. this.QualifierIsNamespace = qualifierIsNamespace;
  3154. }
  3155. public override string/*!*/ ToString(){
  3156. string str = this.Identifier == null ? "" : this.Identifier.ToString();
  3157. if (this.Qualifier == null) return str;
  3158. string separator = this.QualifierIsNamespace ? "::" : "+";
  3159. return this.Qualifier.ToString()+separator+str;
  3160. }
  3161. }
  3162. public class Quantifier : Expression{
  3163. public NodeType QuantifierType;
  3164. public TypeNode SourceType; // the type of elements the quantifier consumes
  3165. public Comprehension Comprehension;
  3166. public Quantifier()
  3167. : base(NodeType.Quantifier){
  3168. }
  3169. public Quantifier(Comprehension comprehension)
  3170. : base(NodeType.Quantifier){
  3171. this.Comprehension = comprehension;
  3172. }
  3173. public Quantifier(NodeType t, Comprehension comprehension)
  3174. : base(NodeType.Quantifier){
  3175. this.QuantifierType = t;
  3176. this.Comprehension = comprehension;
  3177. }
  3178. }
  3179. public enum ComprehensionBindingMode {In, Gets};
  3180. public class ComprehensionBinding : Expression{
  3181. public ComprehensionBindingMode Mode = ComprehensionBindingMode.In;
  3182. public TypeNode TargetVariableType;
  3183. public TypeNode TargetVariableTypeExpression;
  3184. public Expression TargetVariable;
  3185. public TypeNode AsTargetVariableType;
  3186. public TypeNode AsTargetVariableTypeExpression;
  3187. public Expression SourceEnumerable;
  3188. public BlockScope ScopeForTemporaryVariables;
  3189. public ComprehensionBinding()
  3190. : base(NodeType.ComprehensionBinding){
  3191. }
  3192. }
  3193. public enum ComprehensionMode {Reduction, Comprehension};
  3194. // {1,2,3} ==> Comprehension with BindingsAndFilters = null and Elements = [1,2,3]
  3195. // i.e., for a "display", there are no bindings and the elements have one entry per value in the comprehension
  3196. // { int x in A, P(x); T(x); default } ==> Comprehension with BindingsAndFilters = [int x in A, P(x)] and Elements = [T(x), default]
  3197. // i.e., for "true" comprehensions, the list of elements will always have either one or two elements (two if there is a default)
  3198. public class Comprehension : Expression{
  3199. public ComprehensionMode Mode = ComprehensionMode.Comprehension;
  3200. public ExpressionList BindingsAndFilters;
  3201. public ExpressionList Elements;
  3202. public Node nonEnumerableTypeCtor; // used only when the comprehension should generate code for an IList, e.g.
  3203. public Method AddMethod; // used only when the comprehension should generate code for an IList, e.g.
  3204. public TypeNode TemporaryHackToHoldType;
  3205. public Comprehension()
  3206. : base(NodeType.Comprehension){
  3207. }
  3208. public bool IsDisplay{
  3209. get{
  3210. return this.BindingsAndFilters == null;
  3211. }
  3212. }
  3213. }
  3214. public class NameBinding : Expression{
  3215. public Identifier Identifier;
  3216. public MemberList BoundMembers;
  3217. public Expression BoundMember;
  3218. public int LexLevel;
  3219. public Class MostNestedScope;
  3220. public NameBinding()
  3221. : base(NodeType.NameBinding){
  3222. }
  3223. public NameBinding(Identifier identifier, MemberList boundMembers)
  3224. : base(NodeType.NameBinding){
  3225. this.Identifier = identifier;
  3226. this.BoundMembers = boundMembers;
  3227. }
  3228. public NameBinding(Identifier identifier, MemberList boundMembers, SourceContext sctx)
  3229. : base(NodeType.NameBinding){
  3230. this.Identifier = identifier;
  3231. this.BoundMembers = boundMembers;
  3232. this.SourceContext = sctx;
  3233. }
  3234. public NameBinding(Identifier identifier, MemberList boundMembers, Class mostNestedScope, int lexLevel)
  3235. : base(NodeType.NameBinding){
  3236. this.Identifier = identifier;
  3237. this.BoundMembers = boundMembers;
  3238. this.LexLevel = lexLevel;
  3239. this.MostNestedScope = mostNestedScope;
  3240. }
  3241. public NameBinding(Identifier identifier, MemberList boundMembers, Class mostNestedScope, int lexLevel, SourceContext sctx)
  3242. : base(NodeType.NameBinding) {
  3243. this.Identifier = identifier;
  3244. this.BoundMembers = boundMembers;
  3245. this.LexLevel = lexLevel;
  3246. this.MostNestedScope = mostNestedScope;
  3247. this.SourceContext = sctx;
  3248. }
  3249. public override string ToString() {
  3250. return this.Identifier == null ? "" : this.Identifier.ToString();
  3251. }
  3252. }
  3253. public class TemplateInstance : Expression{
  3254. public Expression Expression;
  3255. public TypeNodeList TypeArguments;
  3256. public TypeNodeList TypeArgumentExpressions;
  3257. public bool IsMethodTemplate;
  3258. public MemberList BoundMembers;
  3259. public TemplateInstance()
  3260. : this(null, null){
  3261. }
  3262. public TemplateInstance(Expression expression, TypeNodeList typeArguments)
  3263. : base(NodeType.TemplateInstance){
  3264. this.Expression = expression;
  3265. this.TypeArguments = typeArguments;
  3266. }
  3267. }
  3268. public class StackAlloc : Expression{
  3269. public TypeNode ElementType;
  3270. public TypeNode ElementTypeExpression;
  3271. public Expression NumberOfElements;
  3272. public StackAlloc()
  3273. : base(NodeType.StackAlloc){
  3274. }
  3275. public StackAlloc(TypeNode elementType, Expression numberOfElements, SourceContext sctx)
  3276. : base(NodeType.StackAlloc){
  3277. this.ElementType = this.ElementTypeExpression = elementType;
  3278. this.NumberOfElements = numberOfElements;
  3279. this.SourceContext = sctx;
  3280. }
  3281. }
  3282. #endif
  3283. public class MethodCall : NaryExpression{
  3284. private Expression callee;
  3285. private TypeNode constraint;
  3286. private bool isTailCall;
  3287. #if !MinimalReader
  3288. public Expression CalleeExpression;
  3289. public bool GiveErrorIfSpecialNameMethod;
  3290. public bool ArgumentListIsIncomplete;
  3291. public MethodCall(){
  3292. this.NodeType = NodeType.MethodCall;
  3293. }
  3294. public MethodCall(Expression callee, ExpressionList arguments)
  3295. : base(arguments, NodeType.MethodCall){
  3296. this.callee = this.CalleeExpression = callee;
  3297. this.isTailCall = false;
  3298. }
  3299. #endif
  3300. public MethodCall(Expression callee, ExpressionList arguments, NodeType typeOfCall)
  3301. : base(arguments, typeOfCall){
  3302. this.callee = callee;
  3303. #if !MinimalReader
  3304. this.CalleeExpression = callee;
  3305. #endif
  3306. //this.isTailCall = false;
  3307. }
  3308. #if !MinimalReader
  3309. public MethodCall(Expression callee, ExpressionList arguments, NodeType typeOfCall, TypeNode resultType)
  3310. : this(callee, arguments, typeOfCall){
  3311. this.Type = resultType;
  3312. }
  3313. public MethodCall(Expression callee, ExpressionList arguments, NodeType typeOfCall, TypeNode resultType, SourceContext sctx)
  3314. : this(callee, arguments, typeOfCall, resultType){
  3315. this.SourceContext = sctx;
  3316. }
  3317. #endif
  3318. public Expression Callee{
  3319. get{return this.callee;}
  3320. set{this.callee = value;}
  3321. }
  3322. public bool IsTailCall{
  3323. get{return this.isTailCall;}
  3324. set{this.isTailCall = value;}
  3325. }
  3326. public TypeNode Constraint{
  3327. get{return this.constraint;}
  3328. set{this.constraint = value;}
  3329. }
  3330. }
  3331. public class Construct : NaryExpression{
  3332. private Expression constructor;
  3333. #if !MinimalReader
  3334. public Expression Owner;
  3335. #endif
  3336. public Construct(){
  3337. this.NodeType = NodeType.Construct;
  3338. }
  3339. public Construct(Expression constructor, ExpressionList arguments)
  3340. : base(arguments, NodeType.Construct){
  3341. this.constructor = constructor;
  3342. }
  3343. #if !MinimalReader
  3344. public Construct(Expression constructor, ExpressionList arguments, SourceContext sctx)
  3345. : base(arguments, NodeType.Construct){
  3346. this.constructor = constructor;
  3347. this.SourceContext = sctx;
  3348. }
  3349. public Construct(Expression constructor, ExpressionList arguments, TypeNode type)
  3350. : base(arguments, NodeType.Construct){
  3351. this.constructor = constructor;
  3352. this.Type = type;
  3353. }
  3354. public Construct(Expression constructor, ExpressionList arguments, TypeNode type, SourceContext sctx)
  3355. : base(arguments, NodeType.Construct) {
  3356. this.constructor = constructor;
  3357. this.Type = type;
  3358. this.SourceContext = sctx;
  3359. }
  3360. #endif
  3361. public Expression Constructor{
  3362. get{return this.constructor;}
  3363. set{this.constructor = value;}
  3364. }
  3365. }
  3366. public class ConstructArray : NaryExpression{
  3367. private TypeNode elementType;
  3368. private int rank;
  3369. #if !MinimalReader
  3370. public TypeNode ElementTypeExpression;
  3371. public ExpressionList Initializers;
  3372. public Expression Owner;
  3373. #endif
  3374. public ConstructArray(){
  3375. this.NodeType = NodeType.ConstructArray;
  3376. this.rank = 1;
  3377. }
  3378. public ConstructArray(TypeNode elementType, ExpressionList sizes, ExpressionList initializers)
  3379. : base(sizes, NodeType.ConstructArray){
  3380. this.elementType = elementType;
  3381. this.Operands = sizes;
  3382. this.rank = sizes == null ? 1 : sizes.Count;
  3383. #if !MinimalReader
  3384. this.Initializers = initializers;
  3385. #endif
  3386. }
  3387. #if !MinimalReader
  3388. public ConstructArray(TypeNode elementType, ExpressionList initializers)
  3389. : base(null, NodeType.ConstructArray){
  3390. this.elementType = elementType;
  3391. this.Initializers = initializers;
  3392. this.rank = 1;
  3393. if (elementType != null)
  3394. this.Type = elementType.GetArrayType(1);
  3395. }
  3396. public ConstructArray(TypeNode elementType, int rank, ExpressionList initializers)
  3397. : base(null, NodeType.ConstructArray){
  3398. this.elementType = elementType;
  3399. this.Initializers = initializers;
  3400. this.rank = rank;
  3401. if (elementType != null)
  3402. this.Type = elementType.GetArrayType(1);
  3403. }
  3404. #endif
  3405. public TypeNode ElementType{
  3406. get{return this.elementType;}
  3407. set{this.elementType = value;}
  3408. }
  3409. public int Rank{
  3410. get{return this.rank;}
  3411. set{this.rank = value;}
  3412. }
  3413. }
  3414. #if !MinimalReader
  3415. public class ConstructFlexArray : NaryExpression{
  3416. public TypeNode ElementType;
  3417. public TypeNode ElementTypeExpression;
  3418. public ExpressionList Initializers;
  3419. public ConstructFlexArray(){
  3420. this.NodeType = NodeType.ConstructFlexArray;
  3421. }
  3422. public ConstructFlexArray(TypeNode elementType, ExpressionList sizes, ExpressionList initializers)
  3423. : base(sizes, NodeType.ConstructFlexArray){
  3424. this.ElementType = elementType;
  3425. this.Operands = sizes;
  3426. this.Initializers = initializers;
  3427. }
  3428. }
  3429. public class ConstructDelegate : Expression{
  3430. public TypeNode DelegateType;
  3431. public TypeNode DelegateTypeExpression;
  3432. public Identifier MethodName;
  3433. public Expression TargetObject;
  3434. public ConstructDelegate()
  3435. : base(NodeType.ConstructDelegate){
  3436. }
  3437. public ConstructDelegate(TypeNode delegateType, Expression targetObject, Identifier methodName)
  3438. : base(NodeType.ConstructDelegate) {
  3439. this.DelegateType = delegateType;
  3440. this.MethodName = methodName;
  3441. this.TargetObject = targetObject;
  3442. }
  3443. public ConstructDelegate(TypeNode delegateType, Expression targetObject, Identifier methodName, SourceContext sctx)
  3444. : base(NodeType.ConstructDelegate){
  3445. this.DelegateType = delegateType;
  3446. this.MethodName = methodName;
  3447. this.TargetObject = targetObject;
  3448. this.SourceContext = sctx;
  3449. }
  3450. }
  3451. public class ConstructIterator : Expression{
  3452. public Class State;
  3453. public Block Body;
  3454. public TypeNode ElementType;
  3455. public ConstructIterator()
  3456. : base(NodeType.ConstructIterator){
  3457. }
  3458. public ConstructIterator(Class state, Block body, TypeNode elementType, TypeNode type)
  3459. : base(NodeType.ConstructIterator){
  3460. this.State = state;
  3461. this.Body = body;
  3462. this.ElementType = elementType;
  3463. this.Type = type;
  3464. }
  3465. }
  3466. public class ConstructTuple : Expression{
  3467. public FieldList Fields;
  3468. public ConstructTuple()
  3469. : base(NodeType.ConstructTuple){
  3470. }
  3471. }
  3472. public class CoerceTuple : ConstructTuple{
  3473. public Expression OriginalTuple;
  3474. public Local Temp;
  3475. public CoerceTuple(){
  3476. this.NodeType = NodeType.CoerceTuple;
  3477. }
  3478. }
  3479. #endif
  3480. public class Indexer : NaryExpression{
  3481. #if !MinimalReader
  3482. public Property CorrespondingDefaultIndexedProperty;
  3483. public bool ArgumentListIsIncomplete;
  3484. #endif
  3485. public Indexer(){
  3486. this.NodeType = NodeType.Indexer;
  3487. }
  3488. public Indexer(Expression @object, ExpressionList arguments)
  3489. : base(arguments, NodeType.Indexer){
  3490. this.@object = @object;
  3491. }
  3492. #if !MinimalReader
  3493. public Indexer(Expression Object, ExpressionList arguments, SourceContext sctx)
  3494. : base(arguments, NodeType.Indexer){
  3495. this.@object = Object;
  3496. this.SourceContext = sctx;
  3497. }
  3498. public Indexer(Expression Object, ExpressionList arguments, TypeNode elementType)
  3499. : base(arguments, NodeType.Indexer){
  3500. this.@object = Object;
  3501. this.elementType = this.Type = elementType;
  3502. }
  3503. public Indexer(Expression Object, ExpressionList arguments, TypeNode elementType, SourceContext sctx)
  3504. : base(arguments, NodeType.Indexer){
  3505. this.@object = Object;
  3506. this.elementType = this.Type = elementType;
  3507. this.SourceContext = sctx;
  3508. }
  3509. #endif
  3510. private Expression @object;
  3511. public Expression Object{
  3512. get{return this.@object;}
  3513. set{this.@object = value;}
  3514. }
  3515. private TypeNode elementType;
  3516. /// <summary>
  3517. /// This type is normally expected to be the same the value of Type. However, if the indexer applies to an array of enums, then
  3518. /// Type will be the enum type and ElementType will be the underlying type of the enum.
  3519. /// </summary>
  3520. public TypeNode ElementType{
  3521. get{return this.elementType;}
  3522. set{this.elementType = value;}
  3523. }
  3524. }
  3525. #if !MinimalReader
  3526. public class CollectionEnumerator : Expression{
  3527. public Expression Collection;
  3528. public Method DefaultIndexerGetter;
  3529. public Method LengthPropertyGetter;
  3530. public Method GetEnumerator;
  3531. public Method MoveNext;
  3532. public Method GetCurrent;
  3533. public Local ElementLocal;
  3534. public Expression ElementCoercion;
  3535. public CollectionEnumerator()
  3536. : base(NodeType.CollectionEnumerator){
  3537. }
  3538. }
  3539. /// <summary>
  3540. /// An expression that is used on the left hand as well as the right hand side of an assignment statement. For example, e in (e += 1).
  3541. /// </summary>
  3542. public class LRExpression : Expression{
  3543. public Expression Expression;
  3544. public LocalList Temporaries;
  3545. public ExpressionList SubexpressionsToEvaluateOnce;
  3546. public LRExpression(Expression/*!*/ expression)
  3547. : base(NodeType.LRExpression){
  3548. this.Expression = expression;
  3549. this.Type = expression.Type;
  3550. }
  3551. }
  3552. public class AssignmentExpression : Expression{
  3553. public Statement AssignmentStatement;
  3554. public AssignmentExpression()
  3555. : base(NodeType.AssignmentExpression){
  3556. }
  3557. public AssignmentExpression(AssignmentStatement assignment)
  3558. : base(NodeType.AssignmentExpression){
  3559. this.AssignmentStatement = assignment;
  3560. }
  3561. }
  3562. #endif
  3563. #if !MinimalReader || FxCop
  3564. public class BlockExpression : Expression{
  3565. public Block Block;
  3566. public BlockExpression()
  3567. : base(NodeType.BlockExpression){
  3568. }
  3569. public BlockExpression(Block block)
  3570. : base(NodeType.BlockExpression){
  3571. this.Block = block;
  3572. }
  3573. public BlockExpression(Block block, TypeNode type)
  3574. : base(NodeType.BlockExpression){
  3575. this.Block = block;
  3576. this.Type = type;
  3577. }
  3578. public BlockExpression(Block block, TypeNode type, SourceContext sctx)
  3579. : base(NodeType.BlockExpression){
  3580. this.Block = block;
  3581. this.Type = type;
  3582. this.SourceContext = sctx;
  3583. }
  3584. }
  3585. #endif
  3586. #if !MinimalReader
  3587. public class AnonymousNestedFunction : Expression{
  3588. public ParameterList Parameters;
  3589. public Block Body;
  3590. public Method Method;
  3591. public Expression Invocation;
  3592. public AnonymousNestedFunction()
  3593. : base(NodeType.AnonymousNestedFunction){
  3594. }
  3595. public AnonymousNestedFunction(ParameterList parameters, Block body)
  3596. : base(NodeType.AnonymousNestedFunction){
  3597. this.Parameters = parameters;
  3598. this.Body = body;
  3599. }
  3600. public AnonymousNestedFunction(ParameterList parameters, Block body, SourceContext sctx)
  3601. : base(NodeType.AnonymousNestedFunction){
  3602. this.Parameters = parameters;
  3603. this.Body = body;
  3604. this.SourceContext = sctx;
  3605. }
  3606. }
  3607. #endif
  3608. public class Instruction : Node{
  3609. private OpCode opCode;
  3610. private int offset;
  3611. private object value;
  3612. public Instruction()
  3613. : base(NodeType.Instruction){
  3614. }
  3615. public Instruction(OpCode opCode, int offset)
  3616. : this(opCode, offset, null){
  3617. }
  3618. public Instruction(OpCode opCode, int offset, object value)
  3619. : base(NodeType.Instruction){
  3620. this.opCode = opCode;
  3621. this.offset = offset;
  3622. this.value = value;
  3623. }
  3624. /// <summary>The actual value of the opcode</summary>
  3625. public OpCode OpCode{
  3626. get{return this.opCode;}
  3627. set{this.opCode = value;}
  3628. }
  3629. /// <summary>The offset from the start of the instruction stream of a method</summary>
  3630. public int Offset{
  3631. get{return this.offset;}
  3632. set{this.offset = value;}
  3633. }
  3634. /// <summary>Immediate data such as a string, the address of a branch target, or a metadata reference, such as a Field</summary>
  3635. public object Value{
  3636. get{return this.value;}
  3637. set{this.value = value;}
  3638. }
  3639. }
  3640. public class Statement : Node{
  3641. #if FxCop
  3642. internal int ILOffset;
  3643. #endif
  3644. #if !FxCop && ILOFFSETS
  3645. public int ILOffset;
  3646. #endif
  3647. public Statement(NodeType nodeType)
  3648. : base(nodeType){
  3649. }
  3650. #if !MinimalReader
  3651. public Statement(NodeType nodeType, SourceContext sctx)
  3652. : base(nodeType) {
  3653. this.SourceContext = sctx;
  3654. }
  3655. #endif
  3656. }
  3657. public class Block : Statement{
  3658. private StatementList statements;
  3659. #if !MinimalReader
  3660. public bool Checked;
  3661. public bool SuppressCheck;
  3662. #endif
  3663. #if !MinimalReader || !NoWriter
  3664. public bool HasLocals;
  3665. #endif
  3666. #if !MinimalReader
  3667. public bool IsUnsafe;
  3668. public BlockScope Scope;
  3669. #endif
  3670. public Block()
  3671. : base(NodeType.Block){
  3672. }
  3673. public Block(StatementList statements)
  3674. : base(NodeType.Block){
  3675. this.statements = statements;
  3676. }
  3677. #if !MinimalReader
  3678. public Block(StatementList statements, SourceContext sourceContext)
  3679. : base(NodeType.Block){
  3680. this.SourceContext = sourceContext;
  3681. this.statements = statements;
  3682. }
  3683. public Block(StatementList statements, bool Checked, bool SuppressCheck, bool IsUnsafe)
  3684. : base(NodeType.Block){
  3685. this.Checked = Checked;
  3686. this.IsUnsafe = IsUnsafe;
  3687. this.SuppressCheck = SuppressCheck;
  3688. this.statements = statements;
  3689. }
  3690. public Block(StatementList statements, SourceContext sourceContext, bool Checked, bool SuppressCheck, bool IsUnsafe)
  3691. : base(NodeType.Block){
  3692. this.Checked = Checked;
  3693. this.IsUnsafe = IsUnsafe;
  3694. this.SuppressCheck = SuppressCheck;
  3695. this.SourceContext = sourceContext;
  3696. this.statements = statements;
  3697. }
  3698. public override string ToString() {
  3699. return "B#" + this.UniqueKey.ToString();
  3700. }
  3701. #endif
  3702. public StatementList Statements{
  3703. get{return this.statements;}
  3704. set{this.statements = value;}
  3705. }
  3706. }
  3707. #if !MinimalReader
  3708. public class LabeledStatement : Block{
  3709. public Identifier Label;
  3710. public Statement Statement;
  3711. public LabeledStatement(){
  3712. this.NodeType = NodeType.LabeledStatement;
  3713. }
  3714. }
  3715. public class FunctionDeclaration : Statement{
  3716. public Identifier Name;
  3717. public ParameterList Parameters;
  3718. public TypeNode ReturnType;
  3719. public TypeNode ReturnTypeExpression;
  3720. public Block Body;
  3721. public Method Method;
  3722. public FunctionDeclaration()
  3723. : base(NodeType.FunctionDeclaration){
  3724. }
  3725. public FunctionDeclaration(Identifier name, ParameterList parameters, TypeNode returnType, Block body)
  3726. : base(NodeType.FunctionDeclaration){
  3727. this.Name = name;
  3728. this.Parameters = parameters;
  3729. this.ReturnType = returnType;
  3730. this.Body = body;
  3731. }
  3732. }
  3733. public class Assertion : Statement{
  3734. public Expression Condition;
  3735. // a string that a user wants associated with the assertion
  3736. public Literal userMessage;
  3737. public Assertion()
  3738. : base(NodeType.Assertion){
  3739. }
  3740. public Assertion(Expression condition)
  3741. : base(NodeType.Assertion){
  3742. this.Condition = condition;
  3743. }
  3744. }
  3745. public class Assumption : Statement{
  3746. public Expression Condition;
  3747. // a string that a user wants associated with the assumption
  3748. public Literal userMessage;
  3749. public Assumption()
  3750. : base(NodeType.Assumption){
  3751. }
  3752. public Assumption(Expression condition)
  3753. : base(NodeType.Assumption){
  3754. this.Condition = condition;
  3755. }
  3756. }
  3757. #endif
  3758. public class AssignmentStatement : Statement{
  3759. private NodeType @operator;
  3760. private Expression source;
  3761. private Expression target;
  3762. #if !MinimalReader
  3763. public Method OperatorOverload;
  3764. ///<summary>A Type two which both operands must be coerced before carrying out the operation (if any).</summary>
  3765. public TypeNode UnifiedType;
  3766. #endif
  3767. public AssignmentStatement()
  3768. : base(NodeType.AssignmentStatement){
  3769. this.Operator = NodeType.Nop;
  3770. }
  3771. public AssignmentStatement(Expression target, Expression source)
  3772. : this(target, source, NodeType.Nop){
  3773. }
  3774. #if !MinimalReader
  3775. public AssignmentStatement(Expression target, Expression source, SourceContext context)
  3776. : this(target, source, NodeType.Nop){
  3777. this.SourceContext = context;
  3778. }
  3779. #endif
  3780. public AssignmentStatement(Expression target, Expression source, NodeType @operator)
  3781. : base(NodeType.AssignmentStatement){
  3782. this.target = target;
  3783. this.source = source;
  3784. this.@operator = @operator;
  3785. }
  3786. #if !MinimalReader
  3787. public AssignmentStatement(Expression target, Expression source, NodeType Operator, SourceContext context)
  3788. : this(target, source, Operator){
  3789. this.SourceContext = context;
  3790. }
  3791. #endif
  3792. public NodeType Operator{
  3793. get{return this.@operator;}
  3794. set{this.@operator = value;}
  3795. }
  3796. public Expression Source{
  3797. get{return this.source;}
  3798. set{this.source = value;}
  3799. }
  3800. public Expression Target{
  3801. get{return this.target;}
  3802. set{this.target = value;}
  3803. }
  3804. }
  3805. public class ExpressionStatement : Statement{
  3806. private Expression expression;
  3807. public ExpressionStatement()
  3808. : base(NodeType.ExpressionStatement){
  3809. }
  3810. public ExpressionStatement(Expression expression)
  3811. : base(NodeType.ExpressionStatement){
  3812. this.Expression = expression;
  3813. }
  3814. #if !MinimalReader
  3815. public ExpressionStatement(Expression expression, SourceContext sctx)
  3816. : base(NodeType.ExpressionStatement){
  3817. this.Expression = expression;
  3818. this.SourceContext = sctx;
  3819. }
  3820. #endif
  3821. public Expression Expression{
  3822. get{return this.expression;}
  3823. set{this.expression = value;}
  3824. }
  3825. }
  3826. public class Branch : Statement{
  3827. private Expression condition;
  3828. private bool leavesExceptionBlock;
  3829. internal bool shortOffset;
  3830. private Block target;
  3831. public bool BranchIfUnordered;
  3832. public Branch()
  3833. : base(NodeType.Branch){
  3834. }
  3835. #if !MinimalReader
  3836. public Branch(Expression condition, Block target)
  3837. : this(condition, target, false, false, false){
  3838. }
  3839. public Branch(Expression condition, Block target, SourceContext sourceContext)
  3840. : this(condition, target, false, false, false){
  3841. this.SourceContext = sourceContext;
  3842. }
  3843. public Branch(Expression condition, Block target, SourceContext sourceContext, bool unordered)
  3844. : this(condition, target, false, false, false){
  3845. this.BranchIfUnordered = unordered;
  3846. this.SourceContext = sourceContext;
  3847. }
  3848. #endif
  3849. public Branch(Expression condition, Block target, bool shortOffset, bool unordered, bool leavesExceptionBlock)
  3850. : base(NodeType.Branch){
  3851. this.BranchIfUnordered = unordered;
  3852. this.condition = condition;
  3853. this.leavesExceptionBlock = leavesExceptionBlock;
  3854. this.shortOffset = shortOffset;
  3855. this.target = target;
  3856. }
  3857. public Expression Condition{
  3858. get{return this.condition;}
  3859. set{this.condition = value; }
  3860. }
  3861. public bool LeavesExceptionBlock{
  3862. get{return this.leavesExceptionBlock;}
  3863. set{this.leavesExceptionBlock = value;}
  3864. }
  3865. public bool ShortOffset{
  3866. get{return this.shortOffset;}
  3867. set{this.shortOffset = value;}
  3868. }
  3869. public Block Target{
  3870. get{return this.target;}
  3871. set{this.target = value; }
  3872. }
  3873. }
  3874. #if FxCop
  3875. public class ReturnNode : ExpressionStatement{
  3876. public ReturnNode()
  3877. #else
  3878. public class Return : ExpressionStatement{
  3879. public Return()
  3880. #endif
  3881. : base(){
  3882. this.NodeType = NodeType.Return;
  3883. }
  3884. #if FxCop
  3885. public ReturnNode(Expression expression)
  3886. #else
  3887. public Return(Expression expression)
  3888. #endif
  3889. : base(expression){
  3890. this.NodeType = NodeType.Return;
  3891. }
  3892. #if !MinimalReader
  3893. public Return(SourceContext sctx)
  3894. : base() {
  3895. this.NodeType = NodeType.Return;
  3896. this.SourceContext = sctx;
  3897. }
  3898. public Return(Expression expression, SourceContext sctx)
  3899. : base(expression) {
  3900. this.NodeType = NodeType.Return;
  3901. this.SourceContext = sctx;
  3902. }
  3903. #endif
  3904. }
  3905. #if !MinimalReader
  3906. /// <summary>
  3907. /// Represents the return value in a post condition
  3908. /// </summary>
  3909. public class ReturnValue : Expression
  3910. {
  3911. public ReturnValue() : base(NodeType.ReturnValue)
  3912. { }
  3913. public ReturnValue(SourceContext sc)
  3914. : this()
  3915. {
  3916. this.SourceContext = sc;
  3917. }
  3918. public ReturnValue(TypeNode returnType, SourceContext sc)
  3919. : this(sc)
  3920. {
  3921. this.Type = returnType;
  3922. }
  3923. public ReturnValue(TypeNode returnType)
  3924. : this()
  3925. {
  3926. this.Type = returnType;
  3927. }
  3928. }
  3929. public class Yield : ExpressionStatement{
  3930. public Yield()
  3931. : base(){
  3932. this.NodeType = NodeType.Yield;
  3933. }
  3934. public Yield(Expression expression)
  3935. : base(expression){
  3936. this.NodeType = NodeType.Yield;
  3937. }
  3938. public Yield(Expression expression, SourceContext sctx)
  3939. : base(expression){
  3940. this.NodeType = NodeType.Yield;
  3941. this.SourceContext = sctx;
  3942. }
  3943. }
  3944. public class Try : Statement{
  3945. private CatchList catchers;
  3946. private FilterList filters;
  3947. private FaultHandlerList faultHandlers;
  3948. private Finally finallyClause;
  3949. private Block tryBlock;
  3950. public Try()
  3951. : base(NodeType.Try){
  3952. }
  3953. public Try(Block tryBlock, CatchList catchers, FilterList filters, FaultHandlerList faultHandlers, Finally Finally)
  3954. : base(NodeType.Try){
  3955. this.catchers = catchers;
  3956. this.faultHandlers = faultHandlers;
  3957. this.filters = filters;
  3958. this.finallyClause = Finally;
  3959. this.tryBlock = tryBlock;
  3960. }
  3961. public CatchList Catchers{
  3962. get{return this.catchers;}
  3963. set{this.catchers = value;}
  3964. }
  3965. public FilterList Filters{
  3966. get{return this.filters;}
  3967. set{this.filters = value;}
  3968. }
  3969. public FaultHandlerList FaultHandlers{
  3970. get{return this.faultHandlers;}
  3971. set{this.faultHandlers = value;}
  3972. }
  3973. public Finally Finally{
  3974. get{return this.finallyClause;}
  3975. set{this.finallyClause = value;}
  3976. }
  3977. public Block TryBlock{
  3978. get{return this.tryBlock;}
  3979. set{this.tryBlock = value;}
  3980. }
  3981. }
  3982. public class Catch : Statement{
  3983. private Block block;
  3984. private TypeNode type;
  3985. private Expression variable;
  3986. public TypeNode TypeExpression;
  3987. public Catch()
  3988. : base(NodeType.Catch){
  3989. }
  3990. public Catch(Block block, Expression variable, TypeNode type)
  3991. : base(NodeType.Catch){
  3992. this.block = block;
  3993. this.variable = variable;
  3994. this.type = type;
  3995. }
  3996. public Block Block{
  3997. get{return this.block;}
  3998. set{this.block = value;}
  3999. }
  4000. public TypeNode Type{
  4001. get{return this.type;}
  4002. set{this.type = value;}
  4003. }
  4004. public Expression Variable{
  4005. get{return this.variable;}
  4006. set{this.variable = value;}
  4007. }
  4008. }
  4009. public class Finally : Statement{
  4010. private Block block;
  4011. public Finally()
  4012. : base(NodeType.Finally){
  4013. }
  4014. public Finally(Block block)
  4015. : base(NodeType.Finally){
  4016. this.block = block;
  4017. }
  4018. public Block Block{
  4019. get{return this.block;}
  4020. set{this.block = value;}
  4021. }
  4022. }
  4023. #endif
  4024. public class EndFinally : Statement{
  4025. public EndFinally()
  4026. : base(NodeType.EndFinally){
  4027. }
  4028. }
  4029. #if !MinimalReader || FxCop
  4030. public class Filter : Statement{
  4031. private Block block;
  4032. private Expression expression;
  4033. #if FxCop
  4034. internal int handlerEnd;
  4035. #endif
  4036. public Filter()
  4037. : base(NodeType.Filter){
  4038. }
  4039. public Filter(Block block, Expression expression)
  4040. : base(NodeType.Filter){
  4041. this.block = block;
  4042. this.expression = expression;
  4043. }
  4044. public Block Block{
  4045. get{return this.block;}
  4046. set{this.block = value;}
  4047. }
  4048. public Expression Expression{
  4049. get{return this.expression;}
  4050. set{this.expression = value;}
  4051. }
  4052. }
  4053. #endif
  4054. public class EndFilter : Statement{
  4055. private Expression value;
  4056. public EndFilter()
  4057. : base(NodeType.EndFilter){
  4058. }
  4059. public EndFilter(Expression value)
  4060. : base(NodeType.EndFilter){
  4061. this.value = value;
  4062. }
  4063. public Expression Value{
  4064. get{return this.value;}
  4065. set{this.value = value;}
  4066. }
  4067. }
  4068. #if !MinimalReader || FxCop
  4069. public class FaultHandler : Statement{
  4070. private Block block;
  4071. #if FxCop
  4072. internal int handlerEnd;
  4073. #endif
  4074. public FaultHandler()
  4075. : base(NodeType.FaultHandler){
  4076. }
  4077. public FaultHandler(Block block)
  4078. : base(NodeType.FaultHandler){
  4079. this.block = block;
  4080. }
  4081. public Block Block{
  4082. get{return this.block;}
  4083. set{this.block = value;}
  4084. }
  4085. }
  4086. #endif
  4087. #if FxCop
  4088. public class ThrowNode : Statement{
  4089. #else
  4090. public class Throw : Statement{
  4091. #endif
  4092. private Expression expression;
  4093. #if FxCop
  4094. public ThrowNode()
  4095. : base(NodeType.Throw){
  4096. }
  4097. public ThrowNode(Expression expression)
  4098. : base(NodeType.Throw){
  4099. this.expression = expression;
  4100. }
  4101. #else
  4102. public Throw()
  4103. : base(NodeType.Throw){
  4104. }
  4105. public Throw(Expression expression)
  4106. : base(NodeType.Throw){
  4107. this.expression = expression;
  4108. }
  4109. #endif
  4110. #if !MinimalReader
  4111. public Throw(Expression expression, SourceContext context)
  4112. : base(NodeType.Throw){
  4113. this.expression = expression;
  4114. this.SourceContext = context;
  4115. }
  4116. #endif
  4117. public Expression Expression{
  4118. get{return this.expression;}
  4119. set{this.expression = value;}
  4120. }
  4121. }
  4122. #if !MinimalReader
  4123. public class If : Statement{
  4124. public Expression Condition;
  4125. public Block TrueBlock;
  4126. public Block FalseBlock;
  4127. public SourceContext ConditionContext;
  4128. public SourceContext ElseContext;
  4129. public SourceContext EndIfContext;
  4130. public If()
  4131. : base(NodeType.If){
  4132. }
  4133. public If(Expression condition, Block trueBlock, Block falseBlock)
  4134. : base(NodeType.If){
  4135. this.Condition = condition;
  4136. if (condition != null)
  4137. this.ConditionContext = condition.SourceContext;
  4138. this.TrueBlock = trueBlock;
  4139. this.FalseBlock = falseBlock;
  4140. }
  4141. }
  4142. public class For : Statement{
  4143. public Block Body;
  4144. public Expression Condition;
  4145. public StatementList Incrementer;
  4146. public StatementList Initializer;
  4147. public ExpressionList Invariants;
  4148. public For()
  4149. : base(NodeType.For){
  4150. }
  4151. public For(StatementList initializer, Expression condition, StatementList incrementer, Block body)
  4152. : base(NodeType.For){
  4153. this.Body = body;
  4154. this.Condition = condition;
  4155. this.Incrementer = incrementer;
  4156. this.Initializer = initializer;
  4157. }
  4158. }
  4159. public class ForEach : Statement{
  4160. public Block Body;
  4161. public Expression SourceEnumerable;
  4162. public BlockScope ScopeForTemporaryVariables;
  4163. public Expression TargetVariable;
  4164. public TypeNode TargetVariableType;
  4165. public TypeNode TargetVariableTypeExpression;
  4166. public Expression InductionVariable;
  4167. public ExpressionList Invariants;
  4168. public bool StatementTerminatesNormallyIfEnumerableIsNull = true;
  4169. public bool StatementTerminatesNormallyIfEnumeratorIsNull = true;
  4170. public ForEach()
  4171. : base(NodeType.ForEach){
  4172. }
  4173. public ForEach(TypeNode targetVariableType, Expression targetVariable, Expression sourceEnumerable, Block body)
  4174. : base(NodeType.ForEach){
  4175. this.TargetVariable = targetVariable;
  4176. this.TargetVariableType = targetVariableType;
  4177. this.SourceEnumerable = sourceEnumerable;
  4178. this.Body = body;
  4179. }
  4180. }
  4181. public class Exit : Statement{
  4182. public Literal Level;
  4183. public Exit()
  4184. : base(NodeType.Exit){
  4185. }
  4186. public Exit(Literal level)
  4187. : base(NodeType.Exit){
  4188. this.Level = level;
  4189. }
  4190. }
  4191. public class Continue : Statement{
  4192. public Literal Level;
  4193. public Continue()
  4194. : base(NodeType.Continue){
  4195. }
  4196. public Continue(Literal level)
  4197. : base(NodeType.Continue){
  4198. this.Level = level;
  4199. }
  4200. }
  4201. public class Switch : Statement{
  4202. public SwitchCaseList Cases;
  4203. public Expression Expression;
  4204. public Local Nullable;
  4205. public Expression NullableExpression;
  4206. public BlockScope Scope;
  4207. public Switch()
  4208. : base(NodeType.Switch){
  4209. }
  4210. public Switch(Expression expression, SwitchCaseList cases)
  4211. : base(NodeType.Switch){
  4212. this.Cases = cases;
  4213. this.Expression = expression;
  4214. }
  4215. }
  4216. public class SwitchCase : Node{
  4217. public Block Body;
  4218. public Expression Label;
  4219. public SwitchCase()
  4220. : base(NodeType.SwitchCase){
  4221. }
  4222. public SwitchCase(Expression label, Block body)
  4223. : base(NodeType.SwitchCase){
  4224. this.Body = body;
  4225. this.Label = label;
  4226. }
  4227. }
  4228. public class GotoCase : Statement{
  4229. public Expression CaseLabel;
  4230. public GotoCase(Expression caseLabel)
  4231. : base(NodeType.GotoCase){
  4232. this.CaseLabel = caseLabel;
  4233. }
  4234. }
  4235. #endif
  4236. public class SwitchInstruction : Statement{
  4237. private Expression expression;
  4238. private BlockList targets;
  4239. public SwitchInstruction()
  4240. : base(NodeType.SwitchInstruction){
  4241. }
  4242. public SwitchInstruction(Expression expression, BlockList targets)
  4243. : base(NodeType.SwitchInstruction){
  4244. this.expression = expression;
  4245. this.targets = targets;
  4246. }
  4247. public Expression Expression{
  4248. get{return this.expression;}
  4249. set{this.expression = value;}
  4250. }
  4251. public BlockList Targets{
  4252. get{return this.targets;}
  4253. set{this.targets = value;}
  4254. }
  4255. }
  4256. #if !MinimalReader
  4257. public class Typeswitch : Statement{
  4258. public TypeswitchCaseList Cases;
  4259. public Expression Expression;
  4260. public Typeswitch()
  4261. : base(NodeType.Typeswitch){
  4262. }
  4263. public Typeswitch(Expression expression, TypeswitchCaseList cases)
  4264. : base(NodeType.Typeswitch){
  4265. this.Cases = cases;
  4266. this.Expression = expression;
  4267. }
  4268. }
  4269. public class TypeswitchCase : Node{
  4270. public Block Body;
  4271. public TypeNode LabelType;
  4272. public TypeNode LabelTypeExpression;
  4273. public Expression LabelVariable;
  4274. public TypeswitchCase()
  4275. : base(NodeType.TypeswitchCase){
  4276. }
  4277. public TypeswitchCase(TypeNode labelType, Expression labelVariable, Block body)
  4278. : base(NodeType.TypeswitchCase){
  4279. this.Body = body;
  4280. this.LabelType = labelType;
  4281. this.LabelVariable = labelVariable;
  4282. }
  4283. }
  4284. public class While : Statement{
  4285. public Expression Condition;
  4286. public ExpressionList Invariants;
  4287. public Block Body;
  4288. public While()
  4289. : base(NodeType.While){
  4290. }
  4291. public While(Expression condition, Block body)
  4292. : base(NodeType.While){
  4293. this.Condition = condition;
  4294. this.Body = body;
  4295. }
  4296. }
  4297. public class DoWhile : Statement{
  4298. public Expression Condition;
  4299. public ExpressionList Invariants;
  4300. public Block Body;
  4301. public DoWhile()
  4302. : base(NodeType.DoWhile){
  4303. }
  4304. public DoWhile(Expression condition, Block body)
  4305. : base(NodeType.DoWhile){
  4306. this.Condition = condition;
  4307. this.Body = body;
  4308. }
  4309. }
  4310. public class Repeat : Statement{
  4311. public Expression Condition;
  4312. public Block Body;
  4313. public Repeat()
  4314. : base(NodeType.Repeat){
  4315. }
  4316. public Repeat(Expression condition, Block body)
  4317. : base(NodeType.Repeat){
  4318. this.Condition = condition;
  4319. this.Body = body;
  4320. }
  4321. }
  4322. public class Fixed : Statement{
  4323. public Statement Declarators;
  4324. public Block Body;
  4325. public BlockScope ScopeForTemporaryVariables;
  4326. public Fixed()
  4327. : base(NodeType.Fixed){
  4328. }
  4329. }
  4330. public class Lock : Statement{
  4331. public Expression Guard;
  4332. public Block Body;
  4333. public BlockScope ScopeForTemporaryVariable;
  4334. public Lock()
  4335. : base(NodeType.Lock){
  4336. }
  4337. }
  4338. public class ResourceUse : Statement{
  4339. public Statement ResourceAcquisition;
  4340. public Block Body;
  4341. public BlockScope ScopeForTemporaryVariable;
  4342. public ResourceUse()
  4343. : base(NodeType.ResourceUse){
  4344. }
  4345. }
  4346. public class Goto : Statement{
  4347. public Identifier TargetLabel;
  4348. public Goto()
  4349. : base(NodeType.Goto){
  4350. }
  4351. public Goto(Identifier targetLabel)
  4352. : base(NodeType.Goto){
  4353. this.TargetLabel = targetLabel;
  4354. }
  4355. }
  4356. public class VariableDeclaration : Statement{
  4357. public Expression Initializer;
  4358. public Identifier Name;
  4359. public TypeNode Type;
  4360. public TypeNode TypeExpression;
  4361. public Field Field;
  4362. public VariableDeclaration()
  4363. : base(NodeType.VariableDeclaration){
  4364. }
  4365. public VariableDeclaration(Identifier name, TypeNode type, Expression initializer)
  4366. : base(NodeType.VariableDeclaration){
  4367. this.Initializer = initializer;
  4368. this.Name = name;
  4369. this.Type = type;
  4370. }
  4371. }
  4372. public class LocalDeclaration : Node{
  4373. public Field Field;
  4374. public Identifier Name;
  4375. public Expression InitialValue;
  4376. /// <summary>
  4377. /// Used when converting a declaration with initializer into an assignment statement.
  4378. /// Usually Nop, but could be set to CopyReference to avoid dereferencing on either side.
  4379. /// </summary>
  4380. public NodeType AssignmentNodeType = NodeType.Nop;
  4381. public LocalDeclaration()
  4382. : base(NodeType.LocalDeclaration){
  4383. }
  4384. public LocalDeclaration(Identifier name, Expression initialValue)
  4385. : base(NodeType.LocalDeclaration){
  4386. this.Name = name;
  4387. this.InitialValue = initialValue;
  4388. }
  4389. public LocalDeclaration(Identifier name, Expression initialValue, NodeType assignmentNodeType)
  4390. : base(NodeType.LocalDeclaration){
  4391. this.Name = name;
  4392. this.InitialValue = initialValue;
  4393. this.AssignmentNodeType = assignmentNodeType;
  4394. }
  4395. }
  4396. public class LocalDeclarationsStatement : Statement{
  4397. public bool Constant;
  4398. public bool InitOnly;
  4399. public TypeNode Type;
  4400. public TypeNode TypeExpression;
  4401. public LocalDeclarationList Declarations;
  4402. public LocalDeclarationsStatement()
  4403. : base(NodeType.LocalDeclarationsStatement){
  4404. }
  4405. public LocalDeclarationsStatement(LocalDeclaration ldecl, TypeNode type)
  4406. : base(NodeType.LocalDeclarationsStatement){
  4407. Declarations = new LocalDeclarationList();
  4408. Declarations.Add(ldecl);
  4409. this.Type = type;
  4410. }
  4411. }
  4412. public class StatementSnippet : Statement{
  4413. public IParserFactory ParserFactory;
  4414. public StatementSnippet()
  4415. : base(NodeType.StatementSnippet){
  4416. }
  4417. public StatementSnippet(IParserFactory parserFactory, SourceContext sctx)
  4418. : base(NodeType.StatementSnippet){
  4419. this.ParserFactory = parserFactory;
  4420. this.SourceContext = sctx;
  4421. }
  4422. }
  4423. /// <summary>
  4424. /// Associates an identifier with a type or a namespace or a Uri or a list of assemblies.
  4425. /// In C# alias identifiers are used as root identifiers in qualified expressions, or as identifier prefixes.
  4426. /// </summary>
  4427. public class AliasDefinition : Node{
  4428. /// <summary>The identifier that serves as an alias for the type, namespace, Uri or list of assemblies.</summary>
  4429. public Identifier Alias;
  4430. /// <summary>The list of assemblies being aliased.</summary>
  4431. public AssemblyReferenceList AliasedAssemblies;
  4432. /// <summary>The expression that was (or should be) resolved into a type, namespace or Uri.</summary>
  4433. public Expression AliasedExpression;
  4434. /// <summary>The namespace being aliased.</summary>
  4435. public Identifier AliasedNamespace;
  4436. /// <summary>A reference to the type being aliased.</summary>
  4437. public TypeReference AliasedType;
  4438. /// <summary>The Uri being aliased.</summary>
  4439. public Identifier AliasedUri;
  4440. /// <summary>
  4441. /// If an alias definition conflicts with a type definition and this causes an ambiguity, the conflicting type is stored here
  4442. /// by the code that detects the ambiguity. A later visitor is expected to report an error if this is not null.
  4443. /// </summary>
  4444. public TypeNode ConflictingType;
  4445. public bool RestrictToInterfaces;
  4446. public bool RestrictToClassesAndInterfaces;
  4447. public AliasDefinition()
  4448. : base(NodeType.AliasDefinition){
  4449. }
  4450. public AliasDefinition(Identifier alias, Expression aliasedExpression)
  4451. : base(NodeType.AliasDefinition){
  4452. this.Alias = alias;
  4453. this.AliasedExpression = aliasedExpression;
  4454. }
  4455. public AliasDefinition(Identifier alias, Expression aliasedExpression, SourceContext sctx)
  4456. : base(NodeType.AliasDefinition){
  4457. this.Alias = alias;
  4458. this.AliasedExpression = aliasedExpression;
  4459. this.SourceContext = sctx;
  4460. }
  4461. }
  4462. public class UsedNamespace : Node{
  4463. public Identifier Namespace;
  4464. public Identifier URI;
  4465. public UsedNamespace()
  4466. : base(NodeType.UsedNamespace){
  4467. }
  4468. public UsedNamespace(Identifier Namespace)
  4469. : base(NodeType.UsedNamespace){
  4470. this.Namespace = Namespace;
  4471. }
  4472. public UsedNamespace(Identifier Namespace, SourceContext sctx)
  4473. : base(NodeType.UsedNamespace){
  4474. this.Namespace = Namespace;
  4475. this.SourceContext = sctx;
  4476. }
  4477. }
  4478. #endif
  4479. #if !FxCop
  4480. public class ExceptionHandler : Node{
  4481. private NodeType handlerType;
  4482. private Block tryStartBlock;
  4483. private Block blockAfterTryEnd;
  4484. private Block handlerStartBlock;
  4485. private Block blockAfterHandlerEnd;
  4486. private Block filterExpression;
  4487. private TypeNode filterType;
  4488. public ExceptionHandler()
  4489. : base(NodeType.ExceptionHandler){
  4490. }
  4491. public NodeType HandlerType{
  4492. get{return this.handlerType;}
  4493. set{this.handlerType = value;}
  4494. }
  4495. public Block TryStartBlock{
  4496. get{return this.tryStartBlock;}
  4497. set{this.tryStartBlock = value;}
  4498. }
  4499. public Block BlockAfterTryEnd{
  4500. get{return this.blockAfterTryEnd;}
  4501. set{this.blockAfterTryEnd = value;}
  4502. }
  4503. public Block HandlerStartBlock{
  4504. get{return this.handlerStartBlock;}
  4505. set{this.handlerStartBlock = value;}
  4506. }
  4507. public Block BlockAfterHandlerEnd{
  4508. get{return this.blockAfterHandlerEnd;}
  4509. set{this.blockAfterHandlerEnd = value;}
  4510. }
  4511. public Block FilterExpression{
  4512. get{return this.filterExpression;}
  4513. set{this.filterExpression = value;}
  4514. }
  4515. public TypeNode FilterType{
  4516. get{return this.filterType;}
  4517. set{this.filterType = value;}
  4518. }
  4519. }
  4520. #endif
  4521. public class AttributeNode : Node{
  4522. #if !MinimalReader
  4523. public bool IsPseudoAttribute;
  4524. #endif
  4525. public AttributeNode()
  4526. : base(NodeType.Attribute){
  4527. }
  4528. public AttributeNode(Expression constructor, ExpressionList expressions)
  4529. : base(NodeType.Attribute){
  4530. this.constructor = constructor;
  4531. this.expressions = expressions;
  4532. this.target = AttributeTargets.All;
  4533. }
  4534. #if !MinimalReader
  4535. public AttributeNode(Expression constructor, ExpressionList expressions, AttributeTargets target)
  4536. : base(NodeType.Attribute){
  4537. this.constructor = constructor;
  4538. this.expressions = expressions;
  4539. this.target = target;
  4540. }
  4541. #endif
  4542. private Expression constructor;
  4543. public Expression Constructor{
  4544. get{return this.constructor;}
  4545. set{this.constructor = value;}
  4546. }
  4547. private ExpressionList expressions;
  4548. /// <summary>
  4549. /// Invariant: positional arguments occur first and in order in the expression list. Named arguments
  4550. /// follow posititional arguments in any order.
  4551. /// </summary>
  4552. public ExpressionList Expressions{
  4553. get{return this.expressions;}
  4554. set{this.expressions = value;}
  4555. }
  4556. private AttributeTargets target;
  4557. public AttributeTargets Target{
  4558. get{return this.target;}
  4559. set{this.target = value;}
  4560. }
  4561. private bool allowMultiple;
  4562. public virtual bool AllowMultiple{
  4563. get{
  4564. if (this.usageAttribute == null) this.GetUsageInformation();
  4565. return this.allowMultiple;
  4566. }
  4567. set{
  4568. this.allowMultiple = value;
  4569. }
  4570. }
  4571. private bool inherited;
  4572. public virtual bool Inherited{
  4573. get{
  4574. if (this.usageAttribute == null) this.GetUsageInformation();
  4575. return this.inherited;
  4576. }
  4577. set{
  4578. this.inherited = value;
  4579. }
  4580. }
  4581. private AttributeTargets validOn;
  4582. public virtual AttributeTargets ValidOn{
  4583. get{
  4584. if (this.usageAttribute == null) this.GetUsageInformation();
  4585. return this.validOn;
  4586. }
  4587. set{
  4588. this.validOn = value;
  4589. }
  4590. }
  4591. private TypeNode type;
  4592. public virtual TypeNode Type{
  4593. get{
  4594. if (this.type == null){
  4595. MemberBinding mb = this.Constructor as MemberBinding;
  4596. Member cons = mb == null ? null : mb.BoundMember;
  4597. this.type = cons == null ? null : cons.DeclaringType;
  4598. }
  4599. return this.type;
  4600. }
  4601. set{
  4602. this.type = value;
  4603. }
  4604. }
  4605. private AttributeNode usageAttribute;
  4606. private void GetUsageInformation(){
  4607. AttributeNode attr = null;
  4608. TypeNode attrType = this.Type;
  4609. while (attrType != null){
  4610. attr = attrType.GetAttribute(SystemTypes.AttributeUsageAttribute);
  4611. if (attr != null) break;
  4612. attrType = attrType.BaseType;
  4613. }
  4614. if (attr == null){
  4615. this.usageAttribute = AttributeNode.DoesNotExist;
  4616. return;
  4617. }
  4618. ExpressionList args = attr.Expressions;
  4619. if (args == null || args.Count < 1) return;
  4620. Literal lit = args[0] as Literal;
  4621. if (lit == null || !(lit.Value is int)) {
  4622. #if ExtendedRuntime
  4623. MemberBinding mb = args[0] as MemberBinding;
  4624. if (mb != null) {
  4625. Field f = mb.BoundMember as Field;
  4626. if (f != null && f.IsLiteral) {
  4627. lit = f.Initializer as Literal;
  4628. }
  4629. }
  4630. if (lit == null || !(lit.Value is int))
  4631. #endif
  4632. return;
  4633. }
  4634. //^ assert lit.Value != null;
  4635. this.validOn = (AttributeTargets)(int)lit.Value;
  4636. for (int i = 1, n = args.Count; i < n; i++){
  4637. NamedArgument narg = args[i] as NamedArgument;
  4638. if (narg == null || narg.Name == null) continue;
  4639. lit = narg.Value as Literal;
  4640. if (lit == null) continue;
  4641. if (narg.Name.UniqueIdKey == StandardIds.AllowMultiple.UniqueIdKey){
  4642. if (lit.Value == null || !(lit.Value is bool)) continue;
  4643. this.allowMultiple = (bool)lit.Value;
  4644. }else if (narg.Name.UniqueIdKey == StandardIds.Inherited.UniqueIdKey){
  4645. if (lit.Value == null || !(lit.Value is bool)) continue;
  4646. this.inherited = (bool)lit.Value;
  4647. }
  4648. }
  4649. }
  4650. public static readonly AttributeNode DoesNotExist = new AttributeNode();
  4651. #if !NoReflection
  4652. public virtual System.Attribute GetRuntimeAttribute(){
  4653. MemberBinding mb = this.Constructor as MemberBinding;
  4654. if (mb == null) return null;
  4655. InstanceInitializer constr = mb.BoundMember as InstanceInitializer;
  4656. if (constr == null) return null;
  4657. ParameterList parameters = constr.Parameters;
  4658. int paramCount = parameters == null ? 0 : parameters.Count;
  4659. object[] argumentValues = new object[paramCount];
  4660. ExpressionList argumentExpressions = this.Expressions;
  4661. int exprCount = argumentExpressions == null ? 0 : argumentExpressions.Count;
  4662. for (int i = 0, j = 0; i < paramCount; i++){
  4663. if (j >= exprCount) return null;
  4664. //^ assert argumentExpressions != null;
  4665. Expression argExpr = argumentExpressions[j++];
  4666. Literal lit = argExpr as Literal;
  4667. if (lit == null) continue;
  4668. argumentValues[i] = this.GetCoercedLiteralValue(lit.Type, lit.Value);
  4669. }
  4670. System.Attribute attr = this.ConstructAttribute(constr, argumentValues);
  4671. if (attr == null) return null;
  4672. for (int i = 0; i < exprCount; i++){
  4673. //^ assert argumentExpressions != null;
  4674. NamedArgument namedArg = argumentExpressions[i] as NamedArgument;
  4675. if (namedArg == null) continue;
  4676. if (namedArg.Name == null) continue;
  4677. Literal lit = namedArg.Value as Literal;
  4678. if (lit == null) continue;
  4679. object val = this.GetCoercedLiteralValue(lit.Type, lit.Value);
  4680. if (namedArg.IsCustomAttributeProperty){
  4681. TypeNode t = constr.DeclaringType;
  4682. while (t != null){
  4683. Property prop = t.GetProperty(namedArg.Name);
  4684. if (prop != null){
  4685. this.SetAttributeProperty(prop, attr, val);
  4686. t = null;
  4687. }else
  4688. t = t.BaseType;
  4689. }
  4690. }else{
  4691. TypeNode t = constr.DeclaringType;
  4692. while (t != null){
  4693. Field f = constr.DeclaringType.GetField(namedArg.Name);
  4694. if (f != null){
  4695. System.Reflection.FieldInfo fieldInfo = f.GetFieldInfo();
  4696. if (fieldInfo != null) fieldInfo.SetValue(attr, val);
  4697. t = null;
  4698. }else
  4699. t = t.BaseType;
  4700. }
  4701. }
  4702. }
  4703. return attr;
  4704. }
  4705. /// <summary>
  4706. /// Gets the value of the literal coercing literals of TypeNode, EnumNode, TypeNode[], and EnumNode[] as needed.
  4707. /// </summary>
  4708. /// <param name="type">A TypeNode representing the type of the literal</param>
  4709. /// <param name="value">The value of the literal</param>
  4710. /// <returns>An object that has been coerced to the appropiate runtime type</returns>
  4711. protected object GetCoercedLiteralValue(TypeNode type, object value){
  4712. if (type == null || value == null) return null;
  4713. switch (type.typeCode) {
  4714. case ElementType.Class:
  4715. return ((TypeNode)value).GetRuntimeType();
  4716. case ElementType.ValueType:
  4717. return System.Enum.ToObject(type.GetRuntimeType(), value);
  4718. case ElementType.SzArray:
  4719. return this.GetCoercedArrayLiteral((ArrayType)type, (Array)value);
  4720. default:
  4721. Literal lit = value as Literal;
  4722. if (lit != null && type == CoreSystemTypes.Object && lit.Type is EnumNode)
  4723. return this.GetCoercedLiteralValue(lit.Type, lit.Value);
  4724. break;
  4725. }
  4726. return value;
  4727. }
  4728. /// <summary>
  4729. /// Gets the array literal in arrayValue coercing TypeNode[] and EnumNode[] as needed.
  4730. /// </summary>
  4731. /// <param name="arrayType">A TypeNode representing the array type</param>
  4732. /// <param name="arrayValue">The value of the array literal to coerce</param>
  4733. /// <returns>An Array object that has been coerced to the appropriate runtime type</returns>
  4734. protected Array GetCoercedArrayLiteral(ArrayType arrayType, Array arrayValue){
  4735. if (arrayType == null) return null;
  4736. if (arrayValue == null) return null;
  4737. // Multi-dimensional arrays are not legal in attribute instances according section 17.1.3 of the C# 1.0 spec
  4738. if (arrayValue.Rank != 1) return null;
  4739. TypeNode elemType = arrayType.ElementType;
  4740. if (elemType.typeCode != ElementType.ValueType && elemType.typeCode != ElementType.Class)
  4741. return arrayValue;
  4742. int arraySize = arrayValue.GetLength(0);
  4743. Type et = elemType.GetRuntimeType();
  4744. if (et == null) return null;
  4745. Array val = Array.CreateInstance(et, arraySize);
  4746. for (int i = 0; i < arraySize; i++)
  4747. val.SetValue(this.GetCoercedLiteralValue(elemType, arrayValue.GetValue(i)), i);
  4748. return val;
  4749. }
  4750. private void SetAttributeProperty(Property/*!*/ prop, System.Attribute attr, object val) {
  4751. //This could execute partially trusted code, so set up a very restrictive execution environment
  4752. //TODO: skip this if the attribute is from a trusted assembly
  4753. System.Reflection.PropertyInfo propInfo = prop.GetPropertyInfo();
  4754. if (propInfo == null) return;
  4755. //Because we invoke the setter through reflection, a stack walk is performed. The following two commented-out statements
  4756. //would cause the stack walk to fail.
  4757. //For now, we will run the setter in full trust until we work around this.
  4758. //For VS2005 and later, we will construct a DynamicMethod, wrap it in a delegate, and invoke that.
  4759. //System.Security.PermissionSet perm = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None);
  4760. //perm.PermitOnly();
  4761. try{
  4762. propInfo.SetValue(attr, val, null);
  4763. }catch{}
  4764. }
  4765. private System.Attribute ConstructAttribute(InstanceInitializer/*!*/ constr, object[] argumentValues){
  4766. //This could execute partially trusted code, so set up a very restrictive execution environment
  4767. //TODO: skip this if the attribute is from a trusted assembly
  4768. System.Reflection.ConstructorInfo consInfo = constr.GetConstructorInfo();
  4769. if (consInfo == null) return null;
  4770. //Because we invoke the constructor through reflection, a stack walk is performed. The following two commented-out statements
  4771. //would cause the stack walk to fail.
  4772. //For VS2003 and earlier, we will run the constructor in full trust.
  4773. //For VS2005 and later, we will construct a DynamicMethod, wrap it in a delegate, and invoke that.
  4774. //System.Security.PermissionSet perm = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None);
  4775. //perm.PermitOnly();
  4776. try{
  4777. return consInfo.Invoke(argumentValues) as System.Attribute;
  4778. }catch{}
  4779. return null;
  4780. }
  4781. #endif
  4782. public Expression GetPositionalArgument(int position){
  4783. if (this.Expressions == null || this.Expressions.Count <= position) return null;
  4784. Expression e = this.Expressions[position];
  4785. NamedArgument na = e as NamedArgument;
  4786. if (na != null) return null;
  4787. return e;
  4788. }
  4789. public Expression GetNamedArgument(Identifier name) {
  4790. if (name == null || this.Expressions == null) return null;
  4791. foreach (Expression e in this.Expressions) {
  4792. NamedArgument na = e as NamedArgument;
  4793. if (na == null) continue;
  4794. if (na.Name == null) continue;
  4795. if (na.Name.UniqueIdKey == name.UniqueIdKey) return na.Value;
  4796. }
  4797. return null;
  4798. }
  4799. }
  4800. public class SecurityAttribute : Node{
  4801. public SecurityAttribute()
  4802. : base(NodeType.SecurityAttribute){
  4803. }
  4804. private System.Security.Permissions.SecurityAction action;
  4805. public System.Security.Permissions.SecurityAction Action{
  4806. get{return this.action;}
  4807. set{this.action = value;}
  4808. }
  4809. private AttributeList permissionAttributes;
  4810. public AttributeList PermissionAttributes{
  4811. get{return this.permissionAttributes;}
  4812. set{this.permissionAttributes = value;}
  4813. }
  4814. protected string serializedPermissions;
  4815. public string SerializedPermissions{
  4816. get{
  4817. #if !NoReflection || FxCop
  4818. if (this.serializedPermissions == null && this.PermissionAttributes != null){
  4819. lock (this){
  4820. if (this.serializedPermissions != null) return this.serializedPermissions;
  4821. System.Security.PermissionSet permissions = this.Permissions;
  4822. if (permissions == null) return null;
  4823. System.Security.SecurityElement xml = permissions.ToXml();
  4824. if (xml == null) return null;
  4825. this.serializedPermissions = xml.ToString();
  4826. //TODO: if the target platform is different from the host platform, replace references to host platform
  4827. //assemblies with references to target platform assemblies
  4828. }
  4829. }
  4830. #endif
  4831. return this.serializedPermissions;
  4832. }
  4833. set{
  4834. this.serializedPermissions = value;
  4835. }
  4836. }
  4837. #if !NoReflection || FxCop
  4838. protected System.Security.PermissionSet permissions;
  4839. public System.Security.PermissionSet Permissions{
  4840. get{
  4841. if (this.permissions == null){
  4842. lock (this){
  4843. if (this.permissions != null) return this.permissions;
  4844. System.Security.PermissionSet permissions = null;
  4845. #if !FxCop
  4846. if (this.PermissionAttributes != null){
  4847. permissions = this.InstantiatePermissionAttributes();
  4848. }else if (this.serializedPermissions != null){
  4849. permissions = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None);
  4850. permissions.FromXml(this.GetSecurityElement());
  4851. }
  4852. #elif !TestBuild
  4853. permissions = PermissionsHelper.GetPermissions(this);
  4854. #endif
  4855. this.permissions = permissions;
  4856. }
  4857. }
  4858. return this.permissions;
  4859. }
  4860. set{
  4861. this.permissions = value;
  4862. }
  4863. }
  4864. #endif
  4865. #if !NoReflection
  4866. protected System.Security.SecurityElement GetSecurityElement(){
  4867. #if WHIDBEY
  4868. return System.Security.SecurityElement.FromString(this.serializedPermissions);
  4869. #else
  4870. System.Reflection.Assembly mscorlib = CoreSystemTypes.SystemAssembly.GetRuntimeAssembly();
  4871. if (mscorlib == null) { Debug.Fail(""); return null; }
  4872. Type parserType = mscorlib.GetType("System.Security.Util.Parser", true, false);
  4873. if (parserType == null) { Debug.Fail(""); return null; }
  4874. System.Reflection.MethodInfo getTopElement = parserType.GetMethod("GetTopElement", BindingFlags.NonPublic|BindingFlags.Instance, null, new Type[]{}, null);
  4875. if (getTopElement == null) { Debug.Fail(""); return null; }
  4876. object parser = Activator.CreateInstance(parserType, BindingFlags.Instance|BindingFlags.NonPublic, null, new Object[]{this.serializedPermissions}, null);
  4877. return (System.Security.SecurityElement)getTopElement.Invoke(parser, null);
  4878. #endif
  4879. }
  4880. protected System.Security.PermissionSet InstantiatePermissionAttributes(){
  4881. System.Security.PermissionSet permissions = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None);
  4882. AttributeList permissionAttributes = this.PermissionAttributes;
  4883. for (int i = 0, n = permissionAttributes == null ? 0 : permissionAttributes.Count; i < n; i++){
  4884. //^ assert permissionAttributes != null;
  4885. object result = this.GetPermissionOrSetOfPermissionsFromAttribute(permissionAttributes[i]);
  4886. if (result == null) continue;
  4887. if (result is System.Security.PermissionSet)
  4888. permissions = permissions.Union((System.Security.PermissionSet)result);
  4889. else{
  4890. System.Security.IPermission permission = result as System.Security.IPermission;
  4891. if (permission == null) continue;
  4892. permissions.AddPermission(permission);
  4893. }
  4894. }
  4895. return permissions;
  4896. }
  4897. protected object GetPermissionOrSetOfPermissionsFromAttribute(AttributeNode attr){
  4898. if (attr == null) return null;
  4899. System.Security.Permissions.SecurityAttribute secAttr = attr.GetRuntimeAttribute() as System.Security.Permissions.SecurityAttribute;
  4900. if (secAttr == null) return null;
  4901. System.Security.Permissions.PermissionSetAttribute pSetAttr = secAttr as System.Security.Permissions.PermissionSetAttribute;
  4902. if (pSetAttr != null)
  4903. return pSetAttr.CreatePermissionSet();
  4904. else
  4905. return this.CreatePermission(secAttr);
  4906. }
  4907. private System.Security.IPermission CreatePermission(System.Security.Permissions.SecurityAttribute/*!*/ secAttr) {
  4908. //This could execute partially trusted code, so set up a very restrictive execution environment
  4909. System.Security.PermissionSet perm = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None);
  4910. //TODO: add permissions if the attribute is from a trusted assembly
  4911. perm.PermitOnly();
  4912. try{
  4913. return secAttr.CreatePermission();
  4914. }catch{}
  4915. return null;
  4916. }
  4917. #endif
  4918. }
  4919. public struct Resource{
  4920. private bool isPublic;
  4921. private string name;
  4922. private Module definingModule;
  4923. private byte[] data;
  4924. public bool IsPublic{
  4925. get{return this.isPublic;}
  4926. set{this.isPublic = value;}
  4927. }
  4928. public string Name{
  4929. get{return this.name;}
  4930. set{this.name = value;}
  4931. }
  4932. public Module DefiningModule{
  4933. get{return this.definingModule;}
  4934. set{this.definingModule = value;}
  4935. }
  4936. public byte[] Data{
  4937. get{return this.data;}
  4938. set{this.data = value;}
  4939. }
  4940. }
  4941. public struct Win32Resource{
  4942. private string typeName;
  4943. private int typeId;
  4944. private string name;
  4945. private int id;
  4946. private int languageId;
  4947. private int codePage;
  4948. private byte[] data;
  4949. public string TypeName {
  4950. get{return this.typeName;}
  4951. set{this.typeName = value;}
  4952. }
  4953. public int TypeId{
  4954. get{return this.typeId;}
  4955. set{this.typeId = value;}
  4956. }
  4957. public string Name{
  4958. get{return this.name;}
  4959. set{this.name = value;}
  4960. }
  4961. public int Id{
  4962. get{return this.id;}
  4963. set{this.id = value;}
  4964. }
  4965. public int LanguageId{
  4966. get{return this.languageId;}
  4967. set{this.languageId = value;}
  4968. }
  4969. public int CodePage{
  4970. get{return this.codePage;}
  4971. set{this.codePage = value;}
  4972. }
  4973. public byte[] Data{
  4974. get{return this.data;}
  4975. set{this.data = value;}
  4976. }
  4977. }
  4978. #if FxCop
  4979. public class ModuleNode : Node, IDisposable{
  4980. #else
  4981. public class Module : Node, IDisposable{
  4982. #endif
  4983. internal Reader reader;
  4984. public delegate void TypeNodeListProvider(Module/*!*/ module);
  4985. protected TypeNodeListProvider provideTypeNodeList;
  4986. public delegate TypeNode TypeNodeProvider(Identifier/*!*/ @namespace, Identifier/*!*/ name);
  4987. protected TypeNodeProvider provideTypeNode;
  4988. protected TrivialHashtable namespaceTable = new TrivialHashtable();
  4989. protected NamespaceList namespaceList;
  4990. protected int savedTypesLength;
  4991. public delegate void CustomAttributeProvider(Module/*!*/ module);
  4992. protected CustomAttributeProvider provideCustomAttributes;
  4993. public delegate void ResourceProvider(Module/*!*/ module);
  4994. protected ResourceProvider provideResources;
  4995. public delegate AssemblyNode AssemblyReferenceResolver(AssemblyReference/*!*/ assemblyReference, Module/*!*/ referencingModule);
  4996. public event AssemblyReferenceResolver AssemblyReferenceResolution;
  4997. public event AssemblyReferenceResolver AssemblyReferenceResolutionAfterProbingFailed;
  4998. #if !NoXml
  4999. public delegate XmlDocument DocumentationResolver(Module referencingModule);
  5000. public event DocumentationResolver DocumentationResolution = null;
  5001. #endif
  5002. #if !MinimalReader
  5003. public bool IsNormalized;
  5004. #endif
  5005. #if !NoWriter
  5006. public bool UsePublicKeyTokensForAssemblyReferences = true;
  5007. #endif
  5008. internal int FileAlignment = 512;
  5009. internal readonly static object GlobalLock = new object();
  5010. #if !NoWriter
  5011. public bool StripOptionalModifiersFromLocals = true;
  5012. #endif
  5013. #if FxCop
  5014. public ModuleNode()
  5015. #else
  5016. public Module()
  5017. #endif
  5018. : base(NodeType.Module){
  5019. #if !MinimalReader
  5020. this.IsNormalized = false;
  5021. #endif
  5022. }
  5023. #if FxCop
  5024. public ModuleNode(TypeNodeProvider provider, TypeNodeListProvider listProvider, CustomAttributeProvider provideCustomAttributes, ResourceProvider provideResources)
  5025. #else
  5026. public Module(TypeNodeProvider provider, TypeNodeListProvider listProvider, CustomAttributeProvider provideCustomAttributes, ResourceProvider provideResources)
  5027. #endif
  5028. : base(NodeType.Module){
  5029. this.provideCustomAttributes = provideCustomAttributes;
  5030. this.provideResources = provideResources;
  5031. this.provideTypeNode = provider;
  5032. this.provideTypeNodeList = listProvider;
  5033. #if !MinimalReader
  5034. this.IsNormalized = true;
  5035. #endif
  5036. }
  5037. public virtual void Dispose(){
  5038. if (this.reader != null) this.reader.Dispose();
  5039. this.reader = null;
  5040. ModuleReferenceList mrefs = this.moduleReferences;
  5041. for (int i = 0, n = mrefs == null ? 0 : mrefs.Count; i < n; i++){
  5042. //^ assert mrefs != null;
  5043. ModuleReference mr = mrefs[i];
  5044. if (mr != null && mr.Module == null) continue;
  5045. mr.Module.Dispose();
  5046. }
  5047. this.moduleReferences = null;
  5048. }
  5049. private AssemblyReferenceList assemblyReferences;
  5050. public AssemblyReferenceList AssemblyReferences{
  5051. get{return this.assemblyReferences;}
  5052. set{this.assemblyReferences = value;}
  5053. }
  5054. private AssemblyNode containingAssembly;
  5055. /// <summary>The assembly, if any, that includes this module in its ModuleReferences.</summary>
  5056. public AssemblyNode ContainingAssembly{
  5057. get{return this.containingAssembly;}
  5058. set{this.containingAssembly = value;}
  5059. }
  5060. private ushort dllCharacteristics;
  5061. public ushort DllCharacteristics {
  5062. get { return this.dllCharacteristics; }
  5063. set { this.dllCharacteristics = value; }
  5064. }
  5065. private string directory;
  5066. public string Directory{
  5067. get{return this.directory;}
  5068. set{this.directory = value;}
  5069. }
  5070. private AssemblyHashAlgorithm hashAlgorithm = AssemblyHashAlgorithm.SHA1;
  5071. public AssemblyHashAlgorithm HashAlgorithm{
  5072. get{return this.hashAlgorithm;}
  5073. set{this.hashAlgorithm = value;}
  5074. }
  5075. private byte[] hashValue;
  5076. public byte[] HashValue{
  5077. get{return this.hashValue;}
  5078. set{this.hashValue = value;}
  5079. }
  5080. private ModuleKindFlags kind;
  5081. /// <summary>An enumeration that indicates if the module is an executable, library or resource, and so on.</summary>
  5082. public ModuleKindFlags Kind{
  5083. get{return this.kind;}
  5084. set{this.kind = value;}
  5085. }
  5086. private string location;
  5087. /// <summary>The path of the file from which this module or assembly was loaded or will be stored in.</summary>
  5088. public string Location{
  5089. get{return this.location;}
  5090. set{this.location = value;}
  5091. }
  5092. private System.Guid mvid;
  5093. public System.Guid Mvid{
  5094. get{return this.mvid;}
  5095. set{this.mvid = value;}
  5096. }
  5097. private string targetRuntimeVersion;
  5098. /// <summary>Identifies the version of the CLR that is required to load this module or assembly.</summary>
  5099. public string TargetRuntimeVersion{
  5100. get{return this.targetRuntimeVersion;}
  5101. set{this.targetRuntimeVersion = value;}
  5102. }
  5103. private int linkerMajorVersion = 6;
  5104. public int LinkerMajorVersion{
  5105. get{return this.linkerMajorVersion;}
  5106. set{this.linkerMajorVersion = value;}
  5107. }
  5108. private int linkerMinorVersion;
  5109. public int LinkerMinorVersion{
  5110. get{return this.linkerMinorVersion;}
  5111. set{this.linkerMinorVersion = value;}
  5112. }
  5113. private int metadataFormatMajorVersion;
  5114. public int MetadataFormatMajorVersion{
  5115. get{return this.metadataFormatMajorVersion;}
  5116. set{this.metadataFormatMajorVersion = value;}
  5117. }
  5118. private int metadataFormatMinorVersion;
  5119. public int MetadataFormatMinorVersion{
  5120. get{return this.metadataFormatMinorVersion;}
  5121. set{this.metadataFormatMinorVersion = value;}
  5122. }
  5123. private string name;
  5124. /// <summary>The name of the module or assembly. Includes the file extension if the module is not an assembly.</summary>
  5125. public string Name{
  5126. get{return this.name;}
  5127. set{this.name = value;}
  5128. }
  5129. private PEKindFlags peKind = PEKindFlags.ILonly;
  5130. public PEKindFlags PEKind{
  5131. get{return this.peKind;}
  5132. set{this.peKind = value;}
  5133. }
  5134. private bool trackDebugData;
  5135. public bool TrackDebugData{
  5136. get{return this.trackDebugData;}
  5137. set{this.trackDebugData = value;}
  5138. }
  5139. #if !FxCop
  5140. private ArrayList metadataImportErrors;
  5141. /// <summary>
  5142. /// If any exceptions were encountered while reading in this module, they are recorded here. Since reading is lazy,
  5143. /// this list can grow dynamically during the use of a module.
  5144. /// </summary>
  5145. public ArrayList MetadataImportErrors{
  5146. get{return this.metadataImportErrors;}
  5147. set{this.metadataImportErrors = value;}
  5148. }
  5149. #endif
  5150. protected AttributeList attributes;
  5151. /// <summary>
  5152. /// The attributes associated with this module or assembly. This corresponds to C# custom attributes with the assembly or module target specifier.
  5153. /// </summary>
  5154. public virtual AttributeList Attributes{
  5155. get{
  5156. if (this.attributes != null) return this.attributes;
  5157. if (this.provideCustomAttributes != null){
  5158. lock (Module.GlobalLock){
  5159. if (this.attributes == null)
  5160. this.provideCustomAttributes(this);
  5161. }
  5162. }else
  5163. this.attributes = new AttributeList();
  5164. return this.attributes;
  5165. }
  5166. set{
  5167. this.attributes = value;
  5168. }
  5169. }
  5170. protected SecurityAttributeList securityAttributes;
  5171. /// <summary>
  5172. /// Declarative security for the module or assembly.
  5173. /// </summary>
  5174. public virtual SecurityAttributeList SecurityAttributes{
  5175. get{
  5176. if (this.securityAttributes != null) return this.securityAttributes;
  5177. if (this.provideCustomAttributes != null){
  5178. AttributeList dummy = this.Attributes; //As a side effect, this.securityAttributes gets populated
  5179. if (dummy != null) dummy = null;
  5180. }else
  5181. this.securityAttributes = new SecurityAttributeList();
  5182. return this.securityAttributes;
  5183. }
  5184. set{
  5185. this.securityAttributes = value;
  5186. }
  5187. }
  5188. #if !MinimalReader
  5189. /// <summary>The source code, if any, corresponding to the value in Documentation.</summary>
  5190. public Node DocumentationNode;
  5191. #endif
  5192. #if !NoXml
  5193. protected XmlDocument documentation;
  5194. /// <summary>An XML Document Object Model for a document containing all of the documentation comments applicable to members
  5195. /// defined in this module.</summary>
  5196. public virtual XmlDocument Documentation{
  5197. get{
  5198. XmlDocument documentation = this.documentation;
  5199. if (documentation != null) return documentation;
  5200. if (this.DocumentationResolution != null)
  5201. documentation = this.documentation = this.DocumentationResolution(this);
  5202. if (documentation != null) return documentation;
  5203. XmlDocument doc = null;
  5204. if (this.Directory != null && this.Name != null){
  5205. string fileName = this.Name+".xml";
  5206. System.Globalization.CultureInfo cc = System.Globalization.CultureInfo.CurrentUICulture;
  5207. while (cc != null && cc != System.Globalization.CultureInfo.InvariantCulture) {
  5208. doc = this.ProbeForXmlDocumentation(this.Directory, cc.Name, fileName);
  5209. if (doc != null) break;
  5210. cc = cc.Parent;
  5211. }
  5212. if (doc == null)
  5213. doc = this.ProbeForXmlDocumentation(this.Directory, null, fileName);
  5214. }
  5215. if (doc == null) doc = new XmlDocument();
  5216. return this.documentation = doc;
  5217. }
  5218. set{
  5219. this.documentation = value;
  5220. }
  5221. }
  5222. public virtual XmlDocument ProbeForXmlDocumentation(string dir, string subDir, string fileName){
  5223. try{
  5224. if (dir == null || fileName == null) return null;
  5225. if (subDir != null) dir = Path.Combine(dir, subDir);
  5226. string docFileName = Path.Combine(dir, fileName);
  5227. if (File.Exists(docFileName)){
  5228. XmlDocument doc = new XmlDocument();
  5229. using (TextReader reader = File.OpenText(docFileName)){
  5230. doc.Load(reader);
  5231. return doc;
  5232. }
  5233. }
  5234. }catch(Exception e){
  5235. if (this.MetadataImportErrors == null) this.MetadataImportErrors = new ArrayList();
  5236. this.MetadataImportErrors.Add(e);
  5237. }
  5238. return null;
  5239. }
  5240. #endif
  5241. protected internal static readonly Method NoSuchMethod = new Method();
  5242. protected Method entryPoint;
  5243. /// <summary>If this module is an executable, this method is the one that gets called to start the execution of managed code.</summary>
  5244. public virtual Method EntryPoint{
  5245. get{
  5246. if (this.entryPoint == null){
  5247. if (this.provideCustomAttributes != null){
  5248. AttributeList dummy = this.Attributes; //Gets the entry point as a side effect
  5249. if (dummy != null) dummy = null;
  5250. }else
  5251. this.entryPoint = Module.NoSuchMethod;
  5252. }
  5253. if (this.entryPoint == Module.NoSuchMethod) return null;
  5254. return this.entryPoint;
  5255. }
  5256. set{
  5257. this.entryPoint = value;
  5258. }
  5259. }
  5260. protected ModuleReferenceList moduleReferences;
  5261. /// <summary>The list of modules (excluding assemblies) defining members that are referred to in this module or assembly.</summary>
  5262. public ModuleReferenceList ModuleReferences{
  5263. get{
  5264. //Populating the type list may cause module references to be added
  5265. if (this.Types == null) return this.moduleReferences;
  5266. return this.moduleReferences;
  5267. }
  5268. set{
  5269. this.moduleReferences = value;
  5270. }
  5271. }
  5272. #if !MinimalReader
  5273. public virtual bool ContainsModule(Module module) {
  5274. if (module == null || this.ModuleReferences == null || this.ModuleReferences.Count == 0) return false;
  5275. int n = this.ModuleReferences.Count;
  5276. for (int i = 0; i < n; ++i) {
  5277. ModuleReference mr = this.ModuleReferences[i];
  5278. if (mr == null) continue;
  5279. if (mr.Module == module)
  5280. return true;
  5281. }
  5282. return false;
  5283. }
  5284. #endif
  5285. protected ResourceList resources;
  5286. /// <summary>
  5287. /// A list of managed resources linked or embedded into this module or assembly.
  5288. /// </summary>
  5289. public virtual ResourceList Resources{
  5290. get{
  5291. if (this.resources != null) return this.resources;
  5292. if (this.provideResources != null){
  5293. lock (Module.GlobalLock){
  5294. if (this.resources == null)
  5295. this.provideResources(this);
  5296. }
  5297. }else
  5298. this.resources = new ResourceList();
  5299. return this.resources;
  5300. }
  5301. set{
  5302. this.resources = value;
  5303. }
  5304. }
  5305. protected Win32ResourceList win32Resources;
  5306. /// <summary>
  5307. /// A list of Win32 resources embedded in this module or assembly.
  5308. /// </summary>
  5309. public virtual Win32ResourceList Win32Resources{
  5310. get{
  5311. if (this.win32Resources != null) return this.win32Resources;
  5312. if (this.provideResources != null){
  5313. ResourceList dummy = this.Resources; //gets the win32 resources as as side effect
  5314. if (dummy != null) dummy = null;
  5315. }else
  5316. this.win32Resources = new Win32ResourceList();
  5317. return this.win32Resources;
  5318. }
  5319. set{
  5320. this.win32Resources = value;
  5321. }
  5322. }
  5323. #if !NoWriter
  5324. public virtual void AddWin32ResourceFile(string win32ResourceFilePath){
  5325. if (win32ResourceFilePath == null) return;
  5326. Writer.AddWin32ResourceFileToModule(this, win32ResourceFilePath);
  5327. }
  5328. public virtual void AddWin32ResourceFile(Stream win32ResourceStream){
  5329. if (win32ResourceStream == null) return;
  5330. Writer.AddWin32ResourceFileToModule(this, win32ResourceStream);
  5331. }
  5332. public virtual void AddWin32Icon(string win32IconFilePath){
  5333. if (win32IconFilePath == null) return;
  5334. Writer.AddWin32Icon(this, win32IconFilePath);
  5335. }
  5336. public virtual void AddWin32Icon(Stream win32IconStream){
  5337. Writer.AddWin32Icon(this, win32IconStream);
  5338. }
  5339. public void AddWin32VersionInfo(CompilerOptions options){
  5340. if (options == null) return;
  5341. Writer.AddWin32VersionInfo(this, options);
  5342. }
  5343. #endif
  5344. /// <summary>
  5345. /// Gets the first attribute of the given type in the custom attribute list of this module. Returns null if none found.
  5346. /// This should not be called until the module has been processed to replace symbolic references
  5347. /// to members with references to the actual members.
  5348. /// </summary>
  5349. public virtual AttributeNode GetAttribute(TypeNode attributeType){
  5350. AttributeList attributes = this.GetAttributes(attributeType, 1);
  5351. if (attributes != null && attributes.Count > 0)
  5352. return attributes[0];
  5353. return null;
  5354. }
  5355. public virtual AttributeList GetAttributes(TypeNode attributeType){
  5356. return GetAttributes(attributeType, Int32.MaxValue);
  5357. }
  5358. public virtual AttributeList GetAttributes(TypeNode attributeType, int maxCount){
  5359. AttributeList foundAttributes = new AttributeList();
  5360. if (attributeType == null) return foundAttributes;
  5361. AttributeList attributes = this.Attributes;
  5362. for (int i = 0, count = 0, n = attributes == null ? 0 : attributes.Count; i < n && count < maxCount; i++){
  5363. AttributeNode attr = attributes[i];
  5364. if (attr == null) continue;
  5365. MemberBinding mb = attr.Constructor as MemberBinding;
  5366. if (mb != null){
  5367. if (mb.BoundMember == null) continue;
  5368. if (mb.BoundMember.DeclaringType != attributeType) continue;
  5369. foundAttributes.Add(attr);
  5370. count++;
  5371. continue;
  5372. }
  5373. Literal lit = attr.Constructor as Literal;
  5374. if (lit == null) continue;
  5375. if ((lit.Value as TypeNode) != attributeType) continue;
  5376. foundAttributes.Add(attr);
  5377. count++;
  5378. }
  5379. return foundAttributes;
  5380. }
  5381. #if !NoXml
  5382. protected TrivialHashtable memberDocumentationCache;
  5383. public TrivialHashtable GetMemberDocumentationCache(){
  5384. TrivialHashtable cache = this.memberDocumentationCache;
  5385. if (cache != null) return cache;
  5386. lock(this){
  5387. if (this.memberDocumentationCache != null) return this.memberDocumentationCache;
  5388. XmlDocument doc = this.Documentation;
  5389. if (doc == null && this.ContainingAssembly != null && this.ContainingAssembly != this)
  5390. return this.memberDocumentationCache = this.ContainingAssembly.memberDocumentationCache;
  5391. cache = this.memberDocumentationCache = new TrivialHashtable();
  5392. if (doc == null) return cache;
  5393. XmlNode docElem = doc.DocumentElement;
  5394. if (docElem == null) return cache;
  5395. XmlNode membersNode = null;
  5396. if (docElem.HasChildNodes){
  5397. foreach (XmlNode dec in docElem.ChildNodes)
  5398. if (dec.Name == "members"){membersNode = dec; break;}
  5399. }
  5400. if (membersNode == null) return cache;
  5401. if (membersNode.HasChildNodes){
  5402. foreach (XmlNode member in membersNode.ChildNodes){
  5403. if (member.Name != "member") continue;
  5404. XmlNode nameAttr = member.Attributes.GetNamedItem("name");
  5405. if (nameAttr == null) continue;
  5406. cache[Identifier.For(nameAttr.Value).UniqueIdKey] = member;
  5407. }
  5408. }
  5409. return cache;
  5410. }
  5411. }
  5412. #endif
  5413. protected TrivialHashtable validNamespaces;
  5414. public NamespaceList GetNamespaceList(){
  5415. if (this.reader != null) return this.GetNamespaceListFromReader();
  5416. #if !MinimalReader
  5417. TypeNodeList types = this.Types;
  5418. int n = types == null ? 0 : types.Count;
  5419. if (this.namespaceList == null || n > this.savedTypesLength){
  5420. lock(this){
  5421. if (this.namespaceList != null && this.types != null && this.types.Count == this.savedTypesLength)
  5422. return this.namespaceList;
  5423. NamespaceList nsList = this.namespaceList = new NamespaceList();
  5424. TrivialHashtable nsTable = this.validNamespaces = new TrivialHashtable();
  5425. for (int i = 0; i < n; i++){
  5426. //^ assert this.types != null;
  5427. TypeNode t = this.types[i];
  5428. if (t == null) continue;
  5429. if (t.Namespace == null) t.Namespace = Identifier.Empty;
  5430. Namespace ns = nsTable[t.Namespace.UniqueIdKey] as Namespace;
  5431. if (ns != null){
  5432. if (t.IsPublic) ns.isPublic = true;
  5433. ns.Types.Add(t); continue;
  5434. }
  5435. ns = new Namespace(t.Namespace);
  5436. ns.isPublic = t.IsPublic;
  5437. ns.Types = new TypeNodeList();
  5438. ns.Types.Add(t);
  5439. nsTable[t.Namespace.UniqueIdKey] = ns;
  5440. nsList.Add(ns);
  5441. }
  5442. }
  5443. }
  5444. #endif
  5445. return this.namespaceList;
  5446. }
  5447. private NamespaceList GetNamespaceListFromReader()
  5448. //^ requires this.reader != null;
  5449. {
  5450. if (this.namespaceList == null){
  5451. lock (Module.GlobalLock) {
  5452. this.reader.GetNamespaces();
  5453. NamespaceList nsList = this.namespaceList = this.reader.namespaceList;
  5454. TrivialHashtable nsTable = this.validNamespaces = new TrivialHashtable();
  5455. for (int i = 0, n = nsList == null ? 0 : nsList.Count; i < n; i++) {
  5456. //^ assert nsList != null;
  5457. Namespace ns = nsList[i];
  5458. if (ns == null || ns.Name == null) continue;
  5459. ns.ProvideTypes = new Namespace.TypeProvider(this.GetTypesForNamespace);
  5460. nsTable[ns.Name.UniqueIdKey] = ns;
  5461. }
  5462. }
  5463. }
  5464. return this.namespaceList;
  5465. }
  5466. private void GetTypesForNamespace(Namespace nspace, object handle){
  5467. if (nspace == null || nspace.Name == null) return;
  5468. lock (Module.GlobalLock) {
  5469. int key = nspace.Name.UniqueIdKey;
  5470. TypeNodeList types = this.Types;
  5471. TypeNodeList nsTypes = nspace.Types = new TypeNodeList();
  5472. for (int i = 0, n = types == null ? 0 : types.Count; i < n; i++) {
  5473. TypeNode t = types[i];
  5474. if (t == null || t.Namespace == null) continue;
  5475. if (t.Namespace.UniqueIdKey == key) nsTypes.Add(t);
  5476. }
  5477. }
  5478. }
  5479. public bool IsValidNamespace(Identifier nsName){
  5480. if (nsName == null) return false;
  5481. this.GetNamespaceList();
  5482. //^ assert this.validNamespaces != null;
  5483. return this.validNamespaces[nsName.UniqueIdKey] != null;
  5484. }
  5485. public bool IsValidTypeName(Identifier nsName, Identifier typeName){
  5486. if (nsName == null || typeName == null) return false;
  5487. if (!this.IsValidNamespace(nsName)) return false;
  5488. if (this.reader != null) return this.reader.IsValidTypeName(nsName, typeName);
  5489. return this.GetType(nsName, typeName) != null;
  5490. }
  5491. public Module GetNestedModule(string moduleName){
  5492. if (this.Types == null){ Debug.Assert(false);} //Just get the types to pull in any exported types
  5493. ModuleReferenceList moduleReferences = this.ModuleReferences; //This should now contain all interesting referenced modules
  5494. for (int i = 0, n = moduleReferences == null ? 0 : moduleReferences.Count; i < n; i++){
  5495. ModuleReference mref = moduleReferences[i];
  5496. if (mref == null) continue;
  5497. if (mref.Name == moduleName) return mref.Module;
  5498. }
  5499. return null;
  5500. }
  5501. internal TrivialHashtableUsingWeakReferences/*!*/ StructurallyEquivalentType {
  5502. get {
  5503. if (this.structurallyEquivalentType == null)
  5504. this.structurallyEquivalentType = new TrivialHashtableUsingWeakReferences();
  5505. return this.structurallyEquivalentType;
  5506. }
  5507. }
  5508. private TrivialHashtableUsingWeakReferences structurallyEquivalentType;
  5509. /// <summary>
  5510. /// The identifier represents the structure via some mangling scheme. The result can be either from this module,
  5511. /// or any module this module has a reference to.
  5512. /// </summary>
  5513. public virtual TypeNode GetStructurallyEquivalentType(Identifier ns, Identifier/*!*/ id) {
  5514. return this.GetStructurallyEquivalentType(ns, id, id, true);
  5515. }
  5516. public virtual TypeNode GetStructurallyEquivalentType(Identifier ns, Identifier/*!*/ id, Identifier uniqueMangledName, bool lookInReferencedAssemblies) {
  5517. if (uniqueMangledName == null) uniqueMangledName = id;
  5518. TypeNode result = (TypeNode)this.StructurallyEquivalentType[uniqueMangledName.UniqueIdKey];
  5519. if (result == Class.DoesNotExist) return null;
  5520. if (result != null) return result;
  5521. lock (Module.GlobalLock){
  5522. result = this.GetType(ns, id);
  5523. if (result != null){
  5524. this.StructurallyEquivalentType[uniqueMangledName.UniqueIdKey] = result;
  5525. return result;
  5526. }
  5527. if (!lookInReferencedAssemblies)
  5528. goto notfound;
  5529. AssemblyReferenceList refs = this.AssemblyReferences;
  5530. for (int i = 0, n = refs == null ? 0 : refs.Count; i < n; i++){
  5531. AssemblyReference ar = refs[i];
  5532. if (ar == null) continue;
  5533. AssemblyNode a = ar.Assembly;
  5534. if (a == null) continue;
  5535. result = a.GetType(ns, id);
  5536. if (result != null){
  5537. this.StructurallyEquivalentType[uniqueMangledName.UniqueIdKey] = result;
  5538. return result;
  5539. }
  5540. }
  5541. notfound:
  5542. this.StructurallyEquivalentType[uniqueMangledName.UniqueIdKey] = Class.DoesNotExist;
  5543. return null;
  5544. }
  5545. }
  5546. public virtual TypeNode GetType(Identifier @namespace, Identifier name, bool lookInReferencedAssemblies){
  5547. return this.GetType(@namespace, name, lookInReferencedAssemblies, lookInReferencedAssemblies ? new TrivialHashtable() : null);
  5548. }
  5549. protected virtual TypeNode GetType(Identifier @namespace, Identifier name, bool lookInReferencedAssemblies, TrivialHashtable assembliesAlreadyVisited){
  5550. if (assembliesAlreadyVisited != null) {
  5551. if (assembliesAlreadyVisited[this.UniqueKey] != null) return null;
  5552. assembliesAlreadyVisited[this.UniqueKey] = this;
  5553. }
  5554. TypeNode result = this.GetType(@namespace, name);
  5555. if (result != null || !lookInReferencedAssemblies) return result;
  5556. AssemblyReferenceList refs = this.AssemblyReferences;
  5557. for (int i = 0, n = refs == null ? 0 : refs.Count; i < n; i++) {
  5558. AssemblyReference ar = refs[i];
  5559. if (ar == null) continue;
  5560. AssemblyNode a = ar.Assembly;
  5561. if (a == null) continue;
  5562. result = a.GetType(@namespace, name, true, assembliesAlreadyVisited);
  5563. if (result != null) return result;
  5564. }
  5565. return null;
  5566. }
  5567. public virtual TypeNode GetType(Identifier @namespace, Identifier name){
  5568. if (@namespace == null || name == null) return null;
  5569. TypeNode result = null;
  5570. if (this.namespaceTable == null) this.namespaceTable = new TrivialHashtable();
  5571. TrivialHashtable nsTable = (TrivialHashtable)this.namespaceTable[@namespace.UniqueIdKey];
  5572. if (nsTable != null){
  5573. result = (TypeNode)nsTable[name.UniqueIdKey];
  5574. if (result == Class.DoesNotExist) return null;
  5575. if (result != null) return result;
  5576. }else{
  5577. lock (Module.GlobalLock){
  5578. nsTable = (TrivialHashtable)this.namespaceTable[@namespace.UniqueIdKey];
  5579. if (nsTable == null)
  5580. this.namespaceTable[@namespace.UniqueIdKey] = nsTable = new TrivialHashtable(32);
  5581. }
  5582. }
  5583. if (this.provideTypeNode != null){
  5584. lock (Module.GlobalLock){
  5585. result = (TypeNode)nsTable[name.UniqueIdKey];
  5586. if (result == Class.DoesNotExist) return null;
  5587. if (result != null) return result;
  5588. result = this.provideTypeNode(@namespace, name);
  5589. if (result != null){
  5590. nsTable[name.UniqueIdKey] = result;
  5591. return result;
  5592. }
  5593. nsTable[name.UniqueIdKey] = Class.DoesNotExist;
  5594. return null;
  5595. }
  5596. }
  5597. if (this.types != null && this.types.Count > this.savedTypesLength){
  5598. int n = this.savedTypesLength = this.types.Count;
  5599. for (int i = 0; i < n; i++){
  5600. TypeNode t = this.types[i];
  5601. if (t == null) continue;
  5602. if (t.Namespace == null) t.Namespace = Identifier.Empty;
  5603. nsTable = (TrivialHashtable)this.namespaceTable[t.Namespace.UniqueIdKey];
  5604. if (nsTable == null) this.namespaceTable[t.Namespace.UniqueIdKey] = nsTable = new TrivialHashtable();
  5605. nsTable[t.Name.UniqueIdKey] = t;
  5606. }
  5607. return this.GetType(@namespace, name);
  5608. }
  5609. return null;
  5610. }
  5611. protected internal TypeNodeList types;
  5612. /// <summary>The types contained in this module or assembly.</summary>
  5613. public virtual TypeNodeList Types{
  5614. get{
  5615. if (this.types != null) return this.types;
  5616. if (this.provideTypeNodeList != null){
  5617. lock (Module.GlobalLock){
  5618. if (this.types == null)
  5619. this.provideTypeNodeList(this);
  5620. }
  5621. }else
  5622. this.types = new TypeNodeList();
  5623. return this.types;
  5624. }
  5625. set{
  5626. this.types = value;
  5627. }
  5628. }
  5629. #if !MinimalReader
  5630. protected TrivialHashtable referencedModulesAndAssemblies;
  5631. #endif
  5632. public virtual bool HasReferenceTo(Module module){
  5633. if (module == null) return false;
  5634. AssemblyNode assembly = module as AssemblyNode;
  5635. if (assembly != null){
  5636. AssemblyReferenceList arefs = this.AssemblyReferences;
  5637. for (int i = 0, n = arefs == null ? 0 : arefs.Count; i < n; i++) {
  5638. AssemblyReference aref = arefs[i];
  5639. if (aref == null) continue;
  5640. if (aref.Matches(assembly.Name, assembly.Version, assembly.Culture, assembly.PublicKeyToken))
  5641. return true;
  5642. }
  5643. }
  5644. if (this.ContainingAssembly != module.ContainingAssembly)
  5645. return false;
  5646. ModuleReferenceList mrefs = this.ModuleReferences;
  5647. for (int i = 0, n = mrefs == null ? 0 : mrefs.Count; i < n; i++) {
  5648. //^ assert mrefs != null;
  5649. ModuleReference mref = mrefs[i];
  5650. if (mref == null || mref.Name == null) continue;
  5651. if (0 == PlatformHelpers.StringCompareOrdinalIgnoreCase(mref.Name, module.Name))
  5652. return true;
  5653. }
  5654. return false;
  5655. }
  5656. internal void InitializeAssemblyReferenceResolution(Module referringModule){
  5657. if (this.AssemblyReferenceResolution == null && referringModule != null) {
  5658. this.AssemblyReferenceResolution = referringModule.AssemblyReferenceResolution;
  5659. this.AssemblyReferenceResolutionAfterProbingFailed = referringModule.AssemblyReferenceResolutionAfterProbingFailed;
  5660. }
  5661. }
  5662. #if !MinimalReader
  5663. public static Module GetModule(byte[] buffer){
  5664. return Module.GetModule(buffer, null, false, false, true, false);
  5665. }
  5666. public static Module GetModule(byte[] buffer, IDictionary cache){
  5667. return Module.GetModule(buffer, null, false, false, false, false);
  5668. }
  5669. public static Module GetModule(byte[] buffer, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache){
  5670. return Module.GetModule(buffer, cache, doNotLockFile, getDebugInfo, useGlobalCache, false);
  5671. }
  5672. public static Module GetModule(byte[] buffer, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches){
  5673. if (buffer == null) return null;
  5674. return (new Reader(buffer, cache, doNotLockFile, getDebugInfo, useGlobalCache, false)).ReadModule();
  5675. }
  5676. #endif
  5677. public static Module GetModule(string location){
  5678. return Module.GetModule(location, null, false, false, true, false);
  5679. }
  5680. public static Module GetModule(string location, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache){
  5681. return Module.GetModule(location, null, doNotLockFile, getDebugInfo, useGlobalCache, false);
  5682. }
  5683. public static Module GetModule(string location, IDictionary cache){
  5684. return Module.GetModule(location, cache, false, false, false, false);
  5685. }
  5686. public static Module GetModule(string location, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache){
  5687. return Module.GetModule(location, cache, doNotLockFile, getDebugInfo, useGlobalCache, false);
  5688. }
  5689. public static Module GetModule(string location, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches){
  5690. if (location == null) return null;
  5691. return (new Reader(location, cache, doNotLockFile, getDebugInfo, useGlobalCache, preserveShortBranches)).ReadModule();
  5692. }
  5693. public virtual AssemblyNode Resolve(AssemblyReference assemblyReference){
  5694. if (this.AssemblyReferenceResolution == null) return null;
  5695. return this.AssemblyReferenceResolution(assemblyReference, this);
  5696. }
  5697. public virtual AssemblyNode ResolveAfterProbingFailed(AssemblyReference assemblyReference){
  5698. if (this.AssemblyReferenceResolutionAfterProbingFailed == null) return null;
  5699. return this.AssemblyReferenceResolutionAfterProbingFailed(assemblyReference, this);
  5700. }
  5701. #if !NoWriter
  5702. public virtual void WriteModule(string/*!*/ location, bool writeDebugSymbols) {
  5703. this.Location = location;
  5704. Writer.WritePE(location, writeDebugSymbols, this);
  5705. }
  5706. public virtual void WriteModule(Stream/*!*/ executable, Stream debugSymbols) {
  5707. Writer.WritePE(executable, debugSymbols, this);
  5708. }
  5709. public virtual void WriteModule(out byte[] executable){
  5710. Writer.WritePE(out executable, this);
  5711. }
  5712. public virtual void WriteModule(out byte[] executable, out byte[] debugSymbols){
  5713. Writer.WritePE(out executable, out debugSymbols, this);
  5714. }
  5715. public virtual void WriteModule(string/*!*/ location, System.CodeDom.Compiler.CompilerParameters/*!*/ options) {
  5716. this.Location = location;
  5717. Writer.WritePE(options, this);
  5718. }
  5719. #endif
  5720. #if !NoXml
  5721. public virtual void WriteDocumentation(System.IO.TextWriter doc){
  5722. if (this.documentation == null) return;
  5723. XmlTextWriter xwriter = new XmlTextWriter(doc);
  5724. xwriter.Formatting = Formatting.Indented;
  5725. xwriter.Indentation = 2;
  5726. xwriter.WriteProcessingInstruction("xml", "version=\"1.0\"");
  5727. xwriter.WriteStartElement("doc");
  5728. AssemblyNode assem = this as AssemblyNode;
  5729. if (assem != null){
  5730. xwriter.WriteStartElement("assembly");
  5731. xwriter.WriteElementString("name", assem.Name);
  5732. xwriter.WriteEndElement();
  5733. }
  5734. xwriter.WriteStartElement("members");
  5735. TypeNodeList types = this.Types;
  5736. for (int i = 1, n = types == null ? 0 : types.Count; i < n; i++){
  5737. //^ assert types != null;
  5738. TypeNode t = types[i]; if (t == null) continue;
  5739. t.WriteDocumentation(xwriter);
  5740. }
  5741. xwriter.WriteEndElement();
  5742. xwriter.WriteEndElement();
  5743. xwriter.Close();
  5744. }
  5745. #endif
  5746. #if !NoWriter
  5747. public delegate MethodBodySpecializer/*!*/ MethodBodySpecializerFactory(Module/*!*/ m, TypeNodeList/*!*/ pars, TypeNodeList/*!*/ args);
  5748. public MethodBodySpecializerFactory CreateMethodBodySpecializer;
  5749. public MethodBodySpecializer/*!*/ GetMethodBodySpecializer(TypeNodeList/*!*/ pars, TypeNodeList/*!*/ args) {
  5750. if (CreateMethodBodySpecializer != null)
  5751. return this.CreateMethodBodySpecializer(this, pars, args);
  5752. return new MethodBodySpecializer(this, pars, args);
  5753. }
  5754. #endif
  5755. }
  5756. public class AssemblyNode : Module{ //An assembly is a module with a strong name
  5757. #if !NoWriter
  5758. public string KeyContainerName;
  5759. public byte[] KeyBlob;
  5760. #endif
  5761. #if !NoReflection
  5762. private static Hashtable CompiledAssemblies;// so we can find in-memory compiled assemblies later (contains weak references)
  5763. #endif
  5764. #if !MinimalReader
  5765. protected AssemblyNode contractAssembly;
  5766. /// <summary>A separate assembly that supplied the type and method contracts for this assembly.</summary>
  5767. public virtual AssemblyNode ContractAssembly{
  5768. get{
  5769. return this.contractAssembly;
  5770. }
  5771. set{
  5772. if (this.contractAssembly != null){Debug.Assert(false); return;}
  5773. this.contractAssembly = value;
  5774. if (value == null) return;
  5775. #region Copy over any external references from the contract assembly to this one (if needed)
  5776. // These external references are needed only for the contract deserializer
  5777. AssemblyReferenceList ars = new AssemblyReferenceList();
  5778. AssemblyReferenceList contractReferences = value.AssemblyReferences;
  5779. // see if contractReferences[i] is already in the external references of "this"
  5780. for (int i = 0, n = contractReferences == null ? 0 : contractReferences.Count; i < n; i++){
  5781. //^ assert contractReferences != null;
  5782. AssemblyReference aref = contractReferences[i];
  5783. if (aref == null) continue;
  5784. if (aref.Assembly != this){ // don't copy the contract's external reference to "this"
  5785. int j = 0;
  5786. int m = this.AssemblyReferences == null ? 0 : this.AssemblyReferences.Count;
  5787. while (j < m){
  5788. if (aref.Assembly.Name != null &&
  5789. this.AssemblyReferences[j].Name != null &&
  5790. aref.Assembly.Name.Equals(this.AssemblyReferences[j].Name))
  5791. break;
  5792. j++;
  5793. }
  5794. if (j == m){ // then it wasn't found in the list of the real references
  5795. ars.Add(contractReferences[i]);
  5796. }
  5797. }
  5798. }
  5799. if (this.AssemblyReferences == null)
  5800. this.AssemblyReferences = new AssemblyReferenceList();
  5801. for (int i = 0, n = ars.Count; i < n; i++){
  5802. this.AssemblyReferences.Add(ars[i]);
  5803. }
  5804. #endregion Copy over any external references from the contract assembly to this one (if needed)
  5805. #if ExtendedRuntime
  5806. #region Copy over any assembly-level attributes from the Contracts namespace
  5807. int contractsNamespaceKey = SystemTypes.NonNullType.Namespace.UniqueIdKey;
  5808. // Copy the assembly-level contract attributes over to the shadowed assembly.
  5809. foreach(AttributeNode attr in contractAssembly.Attributes) {
  5810. if(attr.Type != SystemTypes.ShadowsAssemblyAttribute // can't copy this one or the real assembly will be treated as a shadow assembly!
  5811. &&
  5812. attr.Type.Namespace != null && attr.Type.Namespace.UniqueIdKey == contractsNamespaceKey)
  5813. this.Attributes.Add(attr);
  5814. }
  5815. #endregion Copy over any assembly-level attributes from the Contracts namespace
  5816. #endif
  5817. TypeNodeList instantiatedTypes = null;
  5818. if (this.reader != null) instantiatedTypes = this.reader.GetInstantiatedTypes();
  5819. if (instantiatedTypes != null)
  5820. for (int i = 0, n = instantiatedTypes.Count; i < n; i++){
  5821. TypeNode t = instantiatedTypes[i];
  5822. if (t == null) continue;
  5823. if (t.members == null) {
  5824. #if ExtendedRuntime
  5825. // Then will never get to ApplyOutOfBandContracts and will never have any
  5826. // type-level attributes copied over. So need to do this here as well as
  5827. // within ApplyOutOfBandContracts
  5828. TypeNode contractType = this.ContractAssembly.GetType(t.Namespace, t.Name);
  5829. if (contractType == null) continue;
  5830. // Copy the type-level contract attributes over to the shadowed type.
  5831. foreach (AttributeNode attr in contractType.Attributes) {
  5832. if (attr.Type.Namespace != null && attr.Type.Namespace.UniqueIdKey == contractsNamespaceKey)
  5833. t.Attributes.Add(attr);
  5834. }
  5835. #endif
  5836. continue;
  5837. }
  5838. #if ExtendedRuntime
  5839. t.ApplyOutOfBandContracts();
  5840. #endif
  5841. }
  5842. }
  5843. }
  5844. #endif
  5845. internal static readonly AssemblyNode/*!*/ Dummy = new AssemblyNode();
  5846. protected string strongName;
  5847. /// <summary>
  5848. /// A string containing the name, version, culture and key of this assembly, formatted as required by the CLR loader.
  5849. /// </summary>
  5850. public virtual string/*!*/ StrongName{
  5851. get{
  5852. if (this.strongName == null)
  5853. this.strongName = AssemblyNode.GetStrongName(this.Name, this.Version, this.Culture, this.PublicKeyOrToken, (this.Flags & AssemblyFlags.Retargetable) != 0);
  5854. return this.strongName;
  5855. }
  5856. }
  5857. [Obsolete("Please use GetAttribute(TypeNode attributeType)")]
  5858. public virtual AttributeNode GetAttributeByName(TypeNode attributeType){
  5859. if (attributeType == null) return null;
  5860. AttributeList attributes = this.Attributes;
  5861. for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++){
  5862. //^ assert attributes != null;
  5863. AttributeNode attr = attributes[i];
  5864. if (attr == null) continue;
  5865. MemberBinding mb = attr.Constructor as MemberBinding;
  5866. if (mb != null){
  5867. if (mb.BoundMember == null || mb.BoundMember.DeclaringType == null) continue;
  5868. if (mb.BoundMember.DeclaringType.FullName != attributeType.FullName) continue;
  5869. return attr;
  5870. }
  5871. }
  5872. return null;
  5873. }
  5874. /// <summary>
  5875. /// Gets the first attribute of the given type in the custom attribute list of this member. Returns null if none found.
  5876. /// The member is assumed to be either imported, or already in a form suitable for export.
  5877. /// </summary>
  5878. public virtual AttributeNode GetModuleAttribute(TypeNode attributeType){
  5879. if (attributeType == null) return null;
  5880. AttributeList attributes = this.ModuleAttributes;
  5881. for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++){
  5882. //^ assert attributes != null;
  5883. AttributeNode attr = attributes[i];
  5884. if (attr == null) continue;
  5885. MemberBinding mb = attr.Constructor as MemberBinding;
  5886. if (mb != null){
  5887. if (mb.BoundMember == null) continue;
  5888. if (mb.BoundMember.DeclaringType != attributeType) continue;
  5889. return attr;
  5890. }
  5891. Literal lit = attr.Constructor as Literal;
  5892. if (lit == null) continue;
  5893. if ((lit.Value as TypeNode) != attributeType) continue;
  5894. return attr;
  5895. }
  5896. return null;
  5897. }
  5898. public AssemblyNode()
  5899. : base(){
  5900. this.NodeType = NodeType.Assembly;
  5901. this.ContainingAssembly = this;
  5902. }
  5903. public AssemblyNode(TypeNodeProvider provider, TypeNodeListProvider listProvider,
  5904. CustomAttributeProvider provideCustomAttributes, ResourceProvider provideResources, string directory)
  5905. : base(provider, listProvider, provideCustomAttributes, provideResources){
  5906. this.Directory = directory;
  5907. this.NodeType = NodeType.Assembly;
  5908. this.ContainingAssembly = this;
  5909. }
  5910. public override void Dispose(){
  5911. #if !NoReflection
  5912. if (this.cachedRuntimeAssembly != null)
  5913. this.cachedRuntimeAssembly.Dispose();
  5914. this.cachedRuntimeAssembly = null;
  5915. #endif
  5916. lock (Reader.StaticAssemblyCache) {
  5917. foreach (object key in new ArrayList(Reader.StaticAssemblyCache.Keys)){
  5918. if (Reader.StaticAssemblyCache[key] == this)
  5919. Reader.StaticAssemblyCache.Remove(key);
  5920. }
  5921. if(TargetPlatform.AssemblyReferenceForInitialized) {
  5922. AssemblyReference aRef = (AssemblyReference)TargetPlatform.AssemblyReferenceFor[Identifier.For(this.Name).UniqueIdKey];
  5923. if (aRef != null && aRef.Assembly == this){
  5924. aRef.Assembly = null;
  5925. //TODO: what about other static references to the assembly, such as SystemTypes.SystemXmlAssembly?
  5926. }
  5927. }
  5928. }
  5929. base.Dispose();
  5930. }
  5931. private string culture;
  5932. /// <summary>The target culture of any localized resources in this assembly.</summary>
  5933. public string Culture{
  5934. get{return this.culture;}
  5935. set{this.culture = value;}
  5936. }
  5937. private AssemblyFlags flags;
  5938. /// <summary>An enumeration that identifies the what kind of assembly this is.</summary>
  5939. public AssemblyFlags Flags{
  5940. get{return this.flags;}
  5941. set{this.flags = value;}
  5942. }
  5943. private string moduleName;
  5944. /// <summary>Attributes that specifically target a module rather an assembly.</summary>
  5945. public string ModuleName{ //An assembly can have a different name from the module.
  5946. get{return this.moduleName;}
  5947. set{this.moduleName = value;}
  5948. }
  5949. private byte[] publicKeyOrToken;
  5950. /// <summary>The public part of the key pair used to sign this assembly, or a hash of the public key.</summary>
  5951. public byte[] PublicKeyOrToken{
  5952. get{return this.publicKeyOrToken;}
  5953. set{this.publicKeyOrToken = value;}
  5954. }
  5955. private System.Version version;
  5956. /// <summary>The version of this assembly.</summary>
  5957. public System.Version Version{
  5958. get{return this.version;}
  5959. set{this.version = value;}
  5960. }
  5961. private DateTime fileLastWriteTimeUtc;
  5962. public DateTime FileLastWriteTimeUtc{
  5963. get{return this.fileLastWriteTimeUtc;}
  5964. set{this.fileLastWriteTimeUtc = value;}
  5965. }
  5966. protected TypeNodeList exportedTypes;
  5967. /// <summary>
  5968. /// Public types defined in other modules making up this assembly and to which other assemblies may refer to.
  5969. /// </summary>
  5970. public virtual TypeNodeList ExportedTypes{
  5971. get{
  5972. if (this.exportedTypes != null) return this.exportedTypes;
  5973. if (this.provideTypeNodeList != null){
  5974. TypeNodeList types = this.Types; //Gets the exported types as a side-effect
  5975. if (types != null) types = null;
  5976. }else
  5977. this.exportedTypes = new TypeNodeList();
  5978. return this.exportedTypes;
  5979. }
  5980. set{
  5981. this.exportedTypes = value;
  5982. }
  5983. }
  5984. public bool GetDebugSymbols{
  5985. get{
  5986. if (this.reader == null) return false;
  5987. return this.reader.getDebugSymbols;
  5988. }
  5989. set{
  5990. if (this.reader == null) return;
  5991. this.reader.getDebugSymbols = value;
  5992. }
  5993. }
  5994. #if !MinimalReader
  5995. public static AssemblyNode GetAssembly(byte[] buffer){
  5996. return AssemblyNode.GetAssembly(buffer, null, false, false, true, false);
  5997. }
  5998. public static AssemblyNode GetAssembly(byte[] buffer, IDictionary cache){
  5999. return AssemblyNode.GetAssembly(buffer, cache, false, false, false, false);
  6000. }
  6001. public static AssemblyNode GetAssembly(byte[] buffer, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache){
  6002. return AssemblyNode.GetAssembly(buffer, cache, doNotLockFile, getDebugInfo, useGlobalCache, false);
  6003. }
  6004. public static AssemblyNode GetAssembly(byte[] buffer, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches){
  6005. if (buffer == null) return null;
  6006. if (CoreSystemTypes.SystemAssembly == null) Debug.Fail("");
  6007. return (new Reader(buffer, cache, doNotLockFile, getDebugInfo, useGlobalCache, preserveShortBranches)).ReadModule() as AssemblyNode;
  6008. }
  6009. #endif
  6010. public static AssemblyNode GetAssembly(string location){
  6011. return AssemblyNode.GetAssembly(location, null, false, false, true, false);
  6012. }
  6013. public static AssemblyNode GetAssembly(string location, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache){
  6014. return AssemblyNode.GetAssembly(location, null, doNotLockFile, getDebugInfo, useGlobalCache, false);
  6015. }
  6016. public static AssemblyNode GetAssembly(string location, IDictionary cache){
  6017. return AssemblyNode.GetAssembly(location, cache, false, false, false, false);
  6018. }
  6019. public static AssemblyNode GetAssembly(string location, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache){
  6020. return AssemblyNode.GetAssembly(location, cache, doNotLockFile, getDebugInfo, useGlobalCache, false);
  6021. }
  6022. #if !MinimalReader
  6023. /// <summary>
  6024. /// Calls the post load event only if the assembly is not already loaded/found in the cache.
  6025. /// </summary>
  6026. public static AssemblyNode GetAssembly(string location, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, PostAssemblyLoadProcessor postLoadEvent)
  6027. {
  6028. return AssemblyNode.GetAssembly(location, null, doNotLockFile, getDebugInfo, useGlobalCache, false, postLoadEvent);
  6029. }
  6030. public static AssemblyNode GetAssembly(string location, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, PostAssemblyLoadProcessor postLoadEvent)
  6031. {
  6032. return AssemblyNode.GetAssembly(location, cache, doNotLockFile, getDebugInfo, useGlobalCache, false, postLoadEvent);
  6033. }
  6034. public static AssemblyNode GetAssembly(string location, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches)
  6035. {
  6036. return GetAssembly(location, cache, doNotLockFile, getDebugInfo, useGlobalCache, preserveShortBranches, null);
  6037. }
  6038. public static AssemblyNode GetAssembly(string location, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches, PostAssemblyLoadProcessor postLoadEvent)
  6039. {
  6040. if (location == null) return null;
  6041. if (CoreSystemTypes.SystemAssembly == null) Debug.Fail("");
  6042. return (new Reader(location, cache, doNotLockFile, getDebugInfo, useGlobalCache, preserveShortBranches)).ReadModule(postLoadEvent) as AssemblyNode;
  6043. }
  6044. #else
  6045. public static AssemblyNode GetAssembly(string location, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches)
  6046. {
  6047. if (location == null) return null;
  6048. if (CoreSystemTypes.SystemAssembly == null) Debug.Fail("");
  6049. return (new Reader(location, cache, doNotLockFile, getDebugInfo, useGlobalCache, preserveShortBranches)).ReadModule() as AssemblyNode;
  6050. }
  6051. #endif
  6052. #if !MinimalReader || !NoXml || !NoData
  6053. public static AssemblyNode GetAssembly(AssemblyReference assemblyReference){
  6054. return AssemblyNode.GetAssembly(assemblyReference, null, false, false, true, false);
  6055. }
  6056. public static AssemblyNode GetAssembly(AssemblyReference assemblyReference, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache){
  6057. return AssemblyNode.GetAssembly(assemblyReference, null, doNotLockFile, getDebugInfo, useGlobalCache, false);
  6058. }
  6059. public static AssemblyNode GetAssembly(AssemblyReference assemblyReference, IDictionary cache){
  6060. return AssemblyNode.GetAssembly(assemblyReference, cache, false, false, false, false);
  6061. }
  6062. public static AssemblyNode GetAssembly(AssemblyReference assemblyReference, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache){
  6063. return AssemblyNode.GetAssembly(assemblyReference, cache, doNotLockFile, getDebugInfo, useGlobalCache, false);
  6064. }
  6065. public static AssemblyNode GetAssembly(AssemblyReference assemblyReference, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches){
  6066. if (assemblyReference == null) return null;
  6067. if (CoreSystemTypes.SystemAssembly == null) Debug.Fail("");
  6068. Reader reader = new Reader(cache, doNotLockFile, getDebugInfo, useGlobalCache, preserveShortBranches);
  6069. return assemblyReference.Assembly = reader.GetAssemblyFromReference(assemblyReference);
  6070. }
  6071. #endif
  6072. #if !NoReflection
  6073. public static AssemblyNode GetAssembly(System.Reflection.Assembly runtimeAssembly){
  6074. return AssemblyNode.GetAssembly(runtimeAssembly, null, false, true, false);
  6075. }
  6076. public static AssemblyNode GetAssembly(System.Reflection.Assembly runtimeAssembly, IDictionary cache){
  6077. return AssemblyNode.GetAssembly(runtimeAssembly, cache, false, false, false);
  6078. }
  6079. public static AssemblyNode GetAssembly(System.Reflection.Assembly runtimeAssembly, IDictionary cache, bool getDebugInfo, bool useGlobalCache){
  6080. return AssemblyNode.GetAssembly(runtimeAssembly, cache, getDebugInfo, useGlobalCache, false);
  6081. }
  6082. public static AssemblyNode GetAssembly(System.Reflection.Assembly runtimeAssembly, IDictionary cache, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches){
  6083. if (runtimeAssembly == null) return null;
  6084. if (CoreSystemTypes.SystemAssembly == null) Debug.Fail("");
  6085. if (runtimeAssembly.GetName().Name == "mscorlib") {
  6086. return CoreSystemTypes.SystemAssembly;
  6087. }
  6088. if (AssemblyNode.CompiledAssemblies != null) {
  6089. WeakReference weakRef = (WeakReference)AssemblyNode.CompiledAssemblies[runtimeAssembly];
  6090. if (weakRef != null){
  6091. AssemblyNode assem = (AssemblyNode)weakRef.Target;
  6092. if (assem == null) AssemblyNode.CompiledAssemblies.Remove(runtimeAssembly); //Remove the dead WeakReference
  6093. return assem;
  6094. }
  6095. }
  6096. if (runtimeAssembly.Location != null && runtimeAssembly.Location.Length > 0)
  6097. return AssemblyNode.GetAssembly(runtimeAssembly.Location, cache, false, getDebugInfo, useGlobalCache, preserveShortBranches);
  6098. //Get here for in memory assemblies that were not loaded from a known AssemblyNode
  6099. //Need CLR support to handle such assemblies. For now return null.
  6100. return null;
  6101. }
  6102. #endif
  6103. public void SetupDebugReader(string pdbSearchPath){
  6104. if (this.reader == null){Debug.Assert(false); return;}
  6105. this.reader.SetupDebugReader(this.Location, pdbSearchPath);
  6106. }
  6107. internal static string/*!*/ GetStrongName(string name, Version version, string culture, byte[] publicKey, bool retargetable){
  6108. if (version == null) version = new Version();
  6109. StringBuilder result = new StringBuilder();
  6110. result.Append(name);
  6111. result.Append(", Version="); result.Append(version.ToString());
  6112. result.Append(", Culture="); result.Append(((culture == null || culture.Length == 0) ? "neutral" : culture));
  6113. result.Append(AssemblyNode.GetKeyString(publicKey));
  6114. if (retargetable)
  6115. result.Append(", Retargetable=Yes");
  6116. return result.ToString();
  6117. }
  6118. private System.Reflection.AssemblyName assemblyName;
  6119. public System.Reflection.AssemblyName GetAssemblyName(){
  6120. if (this.assemblyName == null){
  6121. System.Reflection.AssemblyName aName = new System.Reflection.AssemblyName();
  6122. if (this.Location != null && this.Location != "unknown:location"){
  6123. StringBuilder sb = new StringBuilder("file:///");
  6124. sb.Append(Path.GetFullPath(this.Location));
  6125. sb.Replace('\\', '/');
  6126. aName.CodeBase = sb.ToString();
  6127. }
  6128. aName.CultureInfo = new System.Globalization.CultureInfo(this.Culture);
  6129. if (this.PublicKeyOrToken != null && this.PublicKeyOrToken.Length > 8)
  6130. aName.Flags = System.Reflection.AssemblyNameFlags.PublicKey;
  6131. if ((this.Flags & AssemblyFlags.Retargetable) != 0)
  6132. aName.Flags |= (System.Reflection.AssemblyNameFlags)AssemblyFlags.Retargetable;
  6133. aName.HashAlgorithm = (System.Configuration.Assemblies.AssemblyHashAlgorithm)this.HashAlgorithm;
  6134. if (this.PublicKeyOrToken != null && this.PublicKeyOrToken.Length > 0)
  6135. aName.SetPublicKey(this.PublicKeyOrToken);
  6136. else
  6137. aName.SetPublicKey(new byte[0]);
  6138. aName.Name = this.Name;
  6139. aName.Version = this.Version;
  6140. switch (this.Flags & AssemblyFlags.CompatibilityMask){
  6141. case AssemblyFlags.NonSideBySideCompatible:
  6142. aName.VersionCompatibility = System.Configuration.Assemblies.AssemblyVersionCompatibility.SameDomain;
  6143. break;
  6144. case AssemblyFlags.NonSideBySideProcess:
  6145. aName.VersionCompatibility = System.Configuration.Assemblies.AssemblyVersionCompatibility.SameProcess;
  6146. break;
  6147. case AssemblyFlags.NonSideBySideMachine:
  6148. aName.VersionCompatibility = System.Configuration.Assemblies.AssemblyVersionCompatibility.SameMachine;
  6149. break;
  6150. }
  6151. this.assemblyName = aName;
  6152. }
  6153. return this.assemblyName;
  6154. }
  6155. #if !NoReflection
  6156. private sealed class CachedRuntimeAssembly : IDisposable{
  6157. internal System.Reflection.Assembly Value;
  6158. internal CachedRuntimeAssembly(System.Reflection.Assembly assembly){
  6159. this.Value = assembly;
  6160. }
  6161. ~CachedRuntimeAssembly(){
  6162. this.Dispose();
  6163. }
  6164. public void Dispose(){
  6165. if (this.Value != null){
  6166. if (AssemblyNode.CompiledAssemblies != null)
  6167. AssemblyNode.CompiledAssemblies.Remove(this.Value);
  6168. }
  6169. this.Value = null;
  6170. GC.SuppressFinalize(this);
  6171. }
  6172. }
  6173. private CachedRuntimeAssembly cachedRuntimeAssembly;
  6174. public System.Reflection.Assembly GetRuntimeAssembly(){
  6175. return this.GetRuntimeAssembly(null, null);
  6176. }
  6177. #endif
  6178. #if !NoReflection
  6179. public System.Reflection.Assembly GetRuntimeAssembly(System.Security.Policy.Evidence evidence){
  6180. return this.GetRuntimeAssembly(evidence, null);
  6181. }
  6182. public System.Reflection.Assembly GetRuntimeAssembly(AppDomain targetAppDomain){
  6183. return this.GetRuntimeAssembly(null, targetAppDomain);
  6184. }
  6185. public System.Reflection.Assembly GetRuntimeAssembly(System.Security.Policy.Evidence evidence, AppDomain targetAppDomain){
  6186. System.Reflection.Assembly result = this.cachedRuntimeAssembly == null ? null : this.cachedRuntimeAssembly.Value;
  6187. if (result == null || evidence != null || targetAppDomain != null){
  6188. lock(this){
  6189. if (this.cachedRuntimeAssembly != null && evidence == null && targetAppDomain == null) return this.cachedRuntimeAssembly.Value;
  6190. if (targetAppDomain == null) targetAppDomain = AppDomain.CurrentDomain;
  6191. if (this.Location != null){
  6192. string name = this.StrongName;
  6193. System.Reflection.Assembly[] alreadyLoadedAssemblies = targetAppDomain.GetAssemblies();
  6194. if (alreadyLoadedAssemblies != null)
  6195. for (int i = 0, n = alreadyLoadedAssemblies.Length; i < n; i++){
  6196. System.Reflection.Assembly a = alreadyLoadedAssemblies[i];
  6197. if (a == null) continue;
  6198. if (a.FullName == name){
  6199. result = a; break;
  6200. }
  6201. }
  6202. if (result == null){
  6203. if (evidence != null)
  6204. result = targetAppDomain.Load(this.GetAssemblyName(), evidence);
  6205. else
  6206. result = targetAppDomain.Load(this.GetAssemblyName());
  6207. }
  6208. }
  6209. #if !NoWriter
  6210. // without the writer, it is impossible to get the runtime
  6211. // assembly for an AssemblyNode which does not correspond
  6212. // to a file on disk, we will return null in that case.
  6213. else{
  6214. byte[] executable = null;
  6215. byte[] debugSymbols = null;
  6216. if ((this.Flags & (AssemblyFlags.EnableJITcompileTracking|AssemblyFlags.DisableJITcompileOptimizer)) != 0){
  6217. this.WriteModule(out executable, out debugSymbols);
  6218. if (evidence != null)
  6219. result = targetAppDomain.Load(executable, debugSymbols, evidence);
  6220. else
  6221. result = targetAppDomain.Load(executable, debugSymbols);
  6222. }else{
  6223. this.WriteModule(out executable);
  6224. if (evidence != null)
  6225. result = targetAppDomain.Load(executable, null, evidence);
  6226. else
  6227. result = targetAppDomain.Load(executable);
  6228. }
  6229. }
  6230. #endif
  6231. if (result != null && evidence == null && targetAppDomain == AppDomain.CurrentDomain){
  6232. this.AddCachedAssembly(result);
  6233. this.cachedRuntimeAssembly = new CachedRuntimeAssembly(result);
  6234. }
  6235. }
  6236. }
  6237. return result;
  6238. }
  6239. private void AddCachedAssembly(System.Reflection.Assembly/*!*/ runtimeAssembly) {
  6240. if (AssemblyNode.CompiledAssemblies == null)
  6241. AssemblyNode.CompiledAssemblies = Hashtable.Synchronized(new Hashtable());
  6242. AssemblyNode.CompiledAssemblies[runtimeAssembly] = new WeakReference(this);
  6243. }
  6244. #endif
  6245. private static string GetKeyString(byte[] publicKey){
  6246. if (publicKey == null) return null;
  6247. int n = publicKey.Length;
  6248. StringBuilder str;
  6249. if (n > 8){
  6250. #if !ROTOR
  6251. System.Security.Cryptography.SHA1 sha1 = new System.Security.Cryptography.SHA1CryptoServiceProvider();
  6252. publicKey = sha1.ComputeHash(publicKey);
  6253. byte[] token = new byte[8];
  6254. for (int i = 0, m = publicKey.Length-1; i < 8; i++)
  6255. token[i] = publicKey[m-i];
  6256. publicKey = token;
  6257. n = 8;
  6258. #else
  6259. n = 0; //TODO: figure out how to compute the token on ROTOR
  6260. #endif
  6261. }
  6262. if (n == 0)
  6263. str = new StringBuilder(", PublicKeyToken=null");
  6264. else
  6265. str = new StringBuilder(", PublicKeyToken=", n*2+17);
  6266. for (int i = 0; i < n; i++)
  6267. str.Append(publicKey[i].ToString("x2"));
  6268. return str.ToString();
  6269. }
  6270. protected TrivialHashtable friends;
  6271. public virtual bool MayAccessInternalTypesOf(AssemblyNode assembly){
  6272. if (this == assembly) return true;
  6273. if (assembly == null || SystemTypes.InternalsVisibleToAttribute == null) return false;
  6274. if (this.friends == null) this.friends = new TrivialHashtable();
  6275. object ob = this.friends[assembly.UniqueKey];
  6276. if (ob == (object)string.Empty) return false;
  6277. if (ob == this) return true;
  6278. AttributeList attributes = assembly.Attributes;
  6279. for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++){
  6280. //^ assert attributes != null;
  6281. AttributeNode attr = attributes[i];
  6282. if (attr == null) continue;
  6283. MemberBinding mb = attr.Constructor as MemberBinding;
  6284. if (mb != null){
  6285. if (mb.BoundMember == null) continue;
  6286. if (mb.BoundMember.DeclaringType != SystemTypes.InternalsVisibleToAttribute) continue;
  6287. }else{
  6288. Literal lit = attr.Constructor as Literal;
  6289. if (lit == null) continue;
  6290. if ((lit.Value as TypeNode) != SystemTypes.InternalsVisibleToAttribute) continue;
  6291. }
  6292. if (attr.Expressions == null || attr.Expressions.Count < 1) continue;
  6293. Literal argLit = attr.Expressions[0] as Literal;
  6294. if (argLit == null) continue;
  6295. string friendName = argLit.Value as string;
  6296. if (friendName == null) continue;
  6297. try{
  6298. AssemblyReference ar = new AssemblyReference(friendName);
  6299. byte[] tok = ar.PublicKeyToken;
  6300. if (tok != null && this.PublicKeyOrToken != null) tok = this.PublicKeyToken;
  6301. if (!ar.Matches(this.Name, ar.Version, ar.Culture, tok)) continue;
  6302. #if !FxCop
  6303. }catch(ArgumentException e){
  6304. if (this.MetadataImportErrors == null) this.MetadataImportErrors = new ArrayList();
  6305. this.MetadataImportErrors.Add(e.Message);
  6306. continue;
  6307. }
  6308. #else
  6309. }finally{}
  6310. #endif
  6311. this.friends[assembly.UniqueKey] = this;
  6312. return true;
  6313. }
  6314. this.friends[assembly.UniqueKey] = string.Empty;
  6315. return false;
  6316. }
  6317. public AssemblyReferenceList GetFriendAssemblies(){
  6318. if (SystemTypes.InternalsVisibleToAttribute == null) return null;
  6319. AttributeList attributes = this.Attributes;
  6320. if (attributes == null) return null;
  6321. int n = attributes.Count; if (n == 0) return null;
  6322. AssemblyReferenceList result = new AssemblyReferenceList(n);
  6323. for (int i = 0; i < n; i++){
  6324. AttributeNode attr = attributes[i];
  6325. if (attr == null) continue;
  6326. MemberBinding mb = attr.Constructor as MemberBinding;
  6327. if (mb != null){
  6328. if (mb.BoundMember == null) continue;
  6329. if (mb.BoundMember.DeclaringType != SystemTypes.InternalsVisibleToAttribute) continue;
  6330. }else{
  6331. Literal lit = attr.Constructor as Literal;
  6332. if (lit == null) continue;
  6333. if ((lit.Value as TypeNode) != SystemTypes.InternalsVisibleToAttribute) continue;
  6334. }
  6335. if (attr.Expressions == null || attr.Expressions.Count < 1) continue;
  6336. Literal argLit = attr.Expressions[0] as Literal;
  6337. if (argLit == null) continue;
  6338. string friendName = argLit.Value as string;
  6339. if (friendName == null) continue;
  6340. result.Add(new AssemblyReference(friendName));
  6341. }
  6342. return result;
  6343. }
  6344. /// <summary>
  6345. /// The attributes associated with this module. This corresponds to C# custom attributes with the module target specifier.
  6346. /// </summary>
  6347. public virtual AttributeList ModuleAttributes {
  6348. get {
  6349. if (this.moduleAttributes != null) return this.moduleAttributes;
  6350. if (this.provideCustomAttributes != null) {
  6351. lock (Module.GlobalLock) {
  6352. if (this.moduleAttributes == null)
  6353. this.provideCustomAttributes(this);
  6354. }
  6355. } else
  6356. this.moduleAttributes = new AttributeList();
  6357. return this.moduleAttributes;
  6358. }
  6359. set {
  6360. this.moduleAttributes = value;
  6361. }
  6362. }
  6363. protected AttributeList moduleAttributes;
  6364. protected byte[] token;
  6365. public virtual byte[] PublicKeyToken{
  6366. get{
  6367. if (this.token != null) return this.token;
  6368. if (this.PublicKeyOrToken == null || this.PublicKeyOrToken.Length == 0) return null;
  6369. if (this.PublicKeyOrToken.Length == 8) return this.token = this.PublicKeyOrToken;
  6370. #if !ROTOR
  6371. System.Security.Cryptography.SHA1 sha1 = new System.Security.Cryptography.SHA1CryptoServiceProvider();
  6372. byte[] hashedKey = sha1.ComputeHash(this.PublicKeyOrToken);
  6373. byte[] token = new byte[8];
  6374. for (int i = 0, n = hashedKey.Length-1; i < 8; i++) token[i] = hashedKey[n-i];
  6375. return this.token = token;
  6376. #else
  6377. return null;
  6378. #endif
  6379. }
  6380. }
  6381. #if !MinimalReader
  6382. public override string ToString() {
  6383. return this.Name;
  6384. }
  6385. public delegate void PostAssemblyLoadProcessor (AssemblyNode loadedAssembly);
  6386. public event PostAssemblyLoadProcessor AfterAssemblyLoad;
  6387. internal PostAssemblyLoadProcessor GetAfterAssemblyLoad()
  6388. {
  6389. return this.AfterAssemblyLoad;
  6390. }
  6391. #endif
  6392. }
  6393. public class AssemblyReference : Node{
  6394. #if !MinimalReader
  6395. public IdentifierList Aliases;
  6396. #endif
  6397. private byte[] token;
  6398. internal Reader Reader;
  6399. public AssemblyReference()
  6400. : base(NodeType.AssemblyReference){
  6401. }
  6402. public AssemblyReference(AssemblyNode/*!*/ assembly)
  6403. : base(NodeType.AssemblyReference){
  6404. this.culture = assembly.Culture;
  6405. this.flags = assembly.Flags & ~AssemblyFlags.PublicKey;
  6406. this.hashValue = assembly.HashValue;
  6407. this.name = assembly.Name;
  6408. this.publicKeyOrToken = assembly.PublicKeyOrToken;
  6409. if (assembly.PublicKeyOrToken != null && assembly.PublicKeyOrToken.Length > 8)
  6410. this.flags |= AssemblyFlags.PublicKey;
  6411. this.location = assembly.Location;
  6412. this.version = assembly.Version;
  6413. this.assembly = assembly;
  6414. }
  6415. #if !MinimalReader
  6416. public AssemblyReference(string assemblyStrongName, SourceContext sctx)
  6417. : this(assemblyStrongName){
  6418. this.SourceContext = sctx;
  6419. }
  6420. #endif
  6421. public AssemblyReference(string assemblyStrongName)
  6422. : base(NodeType.AssemblyReference){
  6423. AssemblyFlags flags = AssemblyFlags.None;
  6424. if (assemblyStrongName == null){Debug.Assert(false); assemblyStrongName = "";}
  6425. int i = 0, n = assemblyStrongName.Length;
  6426. string name = ParseToken(assemblyStrongName, ref i);
  6427. string version = null;
  6428. string culture = null;
  6429. string token = null;
  6430. while (i < n){
  6431. if (assemblyStrongName[i] != ',') throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
  6432. ExceptionStrings.InvalidAssemblyStrongName, assemblyStrongName), "assemblyStrongName");
  6433. i++;
  6434. while (i < n && char.IsWhiteSpace(assemblyStrongName[i])) i++;
  6435. switch (assemblyStrongName[i]){
  6436. case 'v': case 'V': version = ParseAssignment(assemblyStrongName, "Version", ref i); break;
  6437. case 'c': case 'C': culture = ParseAssignment(assemblyStrongName, "Culture", ref i); break;
  6438. case 'p': case 'P':
  6439. if (PlatformHelpers.StringCompareOrdinalIgnoreCase(assemblyStrongName, i, "PublicKeyToken", 0, "PublicKeyToken".Length) == 0)
  6440. token = ParseAssignment(assemblyStrongName, "PublicKeyToken", ref i);
  6441. else {
  6442. token = ParseAssignment(assemblyStrongName, "PublicKey", ref i);
  6443. flags |= AssemblyFlags.PublicKey;
  6444. }
  6445. break;
  6446. case 'r': case 'R':
  6447. string yesOrNo = ParseAssignment(assemblyStrongName, "Retargetable", ref i);
  6448. if (PlatformHelpers.StringCompareOrdinalIgnoreCase(yesOrNo, "Yes") == 0)
  6449. flags |= AssemblyFlags.Retargetable;
  6450. break;
  6451. }
  6452. while (i < n && assemblyStrongName[i] == ']') i++;
  6453. }
  6454. while (i < n && char.IsWhiteSpace(assemblyStrongName[i])) i++;
  6455. if (i < n) throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
  6456. ExceptionStrings.InvalidAssemblyStrongName, assemblyStrongName), "assemblyStrongName");
  6457. if (PlatformHelpers.StringCompareOrdinalIgnoreCase(culture, "neutral") == 0)
  6458. culture = null;
  6459. if (PlatformHelpers.StringCompareOrdinalIgnoreCase(token, "null") == 0)
  6460. token = null;
  6461. byte[] tok = null;
  6462. if (token != null && (n = token.Length) > 0){
  6463. if (n > 16){
  6464. ArrayList tokArr = new ArrayList();
  6465. if (n % 2 == 1){
  6466. tokArr.Add(byte.Parse(token.Substring(0, 1), System.Globalization.NumberStyles.HexNumber, null));
  6467. n--;
  6468. }
  6469. for (i = 0; i < n; i += 2) {
  6470. #if WHIDBEY
  6471. byte b = 0;
  6472. bool goodByte = byte.TryParse(token.Substring(i, 2), System.Globalization.NumberStyles.HexNumber, null, out b);
  6473. Debug.Assert(goodByte);
  6474. #else
  6475. byte b = byte.Parse(token.Substring(i, 2), System.Globalization.NumberStyles.HexNumber, null);
  6476. #endif
  6477. tokArr.Add(b);
  6478. }
  6479. tok = (byte[])tokArr.ToArray(typeof(byte));
  6480. }else{
  6481. ulong tk = ulong.Parse(token, System.Globalization.NumberStyles.HexNumber, null);
  6482. tok = new byte[8];
  6483. tok[0] = (byte)(tk >> 56);
  6484. tok[1] = (byte)(tk >> 48);
  6485. tok[2] = (byte)(tk >> 40);
  6486. tok[3] = (byte)(tk >> 32);
  6487. tok[4] = (byte)(tk >> 24);
  6488. tok[5] = (byte)(tk >> 16);
  6489. tok[6] = (byte)(tk >> 8);
  6490. tok[7] = (byte)tk;
  6491. }
  6492. }
  6493. this.culture = culture;
  6494. this.name = name;
  6495. this.publicKeyOrToken = tok;
  6496. this.version = version == null || version.Length == 0 ? null : new Version(version);
  6497. this.flags = flags;
  6498. }
  6499. private static string ParseToken(string/*!*/ assemblyStrongName, ref int i) {
  6500. Debug.Assert(assemblyStrongName != null);
  6501. int n = assemblyStrongName.Length;
  6502. Debug.Assert(0 <= i && i < n);
  6503. while (i < n && char.IsWhiteSpace(assemblyStrongName[i])) i++;
  6504. StringBuilder sb = new StringBuilder(n);
  6505. while (i < n){
  6506. char ch = assemblyStrongName[i];
  6507. if (ch == ',' || ch == ']' || char.IsWhiteSpace(ch)) break;
  6508. sb.Append(ch);
  6509. i++;
  6510. }
  6511. while (i < n && char.IsWhiteSpace(assemblyStrongName[i])) i++;
  6512. return sb.ToString();
  6513. }
  6514. private static string ParseAssignment(string/*!*/ assemblyStrongName, string/*!*/ target, ref int i) {
  6515. Debug.Assert(assemblyStrongName != null && target != null);
  6516. int n = assemblyStrongName.Length;
  6517. Debug.Assert(0 < i && i < n);
  6518. if (PlatformHelpers.StringCompareOrdinalIgnoreCase(assemblyStrongName, i, target, 0, target.Length) != 0)
  6519. goto throwError;
  6520. i += target.Length;
  6521. while (i < n && char.IsWhiteSpace(assemblyStrongName[i])) i++;
  6522. if (i >= n || assemblyStrongName[i] != '=') goto throwError;
  6523. i++;
  6524. if (i >= n) goto throwError;
  6525. return ParseToken(assemblyStrongName, ref i);
  6526. throwError:
  6527. throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
  6528. ExceptionStrings.InvalidAssemblyStrongName, assemblyStrongName), "assemblyStrongName");
  6529. }
  6530. private string culture;
  6531. public string Culture{
  6532. get{return this.culture;}
  6533. set{this.culture = value;}
  6534. }
  6535. private AssemblyFlags flags;
  6536. public AssemblyFlags Flags{
  6537. get{return this.flags;}
  6538. set{this.flags = value;}
  6539. }
  6540. private byte[] hashValue;
  6541. public byte[] HashValue{
  6542. get{return this.hashValue;}
  6543. set{this.hashValue = value;}
  6544. }
  6545. private string name;
  6546. public string Name{
  6547. get{return this.name;}
  6548. set{this.name = value;}
  6549. }
  6550. private byte[] publicKeyOrToken;
  6551. public byte[] PublicKeyOrToken{
  6552. get{return this.publicKeyOrToken;}
  6553. set{this.publicKeyOrToken = value;}
  6554. }
  6555. private System.Version version;
  6556. public System.Version Version{
  6557. get{return this.version;}
  6558. set{this.version = value;}
  6559. }
  6560. private string location;
  6561. public string Location{
  6562. get{return this.location;}
  6563. set{this.location = value;}
  6564. }
  6565. protected internal AssemblyNode assembly;
  6566. public virtual AssemblyNode Assembly{
  6567. get{
  6568. if (this.assembly != null) return this.assembly;
  6569. if (this.Reader != null)
  6570. return this.assembly = this.Reader.GetAssemblyFromReference(this);
  6571. return null;
  6572. }
  6573. set{
  6574. this.assembly = value;
  6575. }
  6576. }
  6577. protected string strongName;
  6578. public virtual string StrongName{
  6579. get{
  6580. if (this.strongName == null)
  6581. this.strongName = AssemblyNode.GetStrongName(this.Name, this.Version, this.Culture, this.PublicKeyOrToken, (this.Flags & AssemblyFlags.Retargetable) != 0);
  6582. return this.strongName;
  6583. }
  6584. }
  6585. private System.Reflection.AssemblyName assemblyName;
  6586. public System.Reflection.AssemblyName GetAssemblyName(){
  6587. if (this.assemblyName == null){
  6588. System.Reflection.AssemblyName aName = new System.Reflection.AssemblyName();
  6589. aName.CultureInfo = new System.Globalization.CultureInfo(this.Culture == null ? "" : this.Culture);
  6590. if (this.PublicKeyOrToken != null && this.PublicKeyOrToken.Length > 8)
  6591. aName.Flags = System.Reflection.AssemblyNameFlags.PublicKey;
  6592. if ((this.Flags & AssemblyFlags.Retargetable) != 0)
  6593. aName.Flags |= (System.Reflection.AssemblyNameFlags)AssemblyFlags.Retargetable;
  6594. aName.HashAlgorithm = System.Configuration.Assemblies.AssemblyHashAlgorithm.SHA1;
  6595. if (this.PublicKeyOrToken != null){
  6596. if (this.PublicKeyOrToken.Length > 8)
  6597. aName.SetPublicKey(this.PublicKeyOrToken);
  6598. else if (this.PublicKeyOrToken.Length > 0)
  6599. aName.SetPublicKeyToken(this.PublicKeyOrToken);
  6600. }
  6601. else
  6602. aName.SetPublicKey(new byte[0]);
  6603. aName.Name = this.Name;
  6604. aName.Version = this.Version;
  6605. switch (this.Flags & AssemblyFlags.CompatibilityMask){
  6606. case AssemblyFlags.NonSideBySideCompatible:
  6607. aName.VersionCompatibility = System.Configuration.Assemblies.AssemblyVersionCompatibility.SameDomain;
  6608. break;
  6609. case AssemblyFlags.NonSideBySideProcess:
  6610. aName.VersionCompatibility = System.Configuration.Assemblies.AssemblyVersionCompatibility.SameProcess;
  6611. break;
  6612. case AssemblyFlags.NonSideBySideMachine:
  6613. aName.VersionCompatibility = System.Configuration.Assemblies.AssemblyVersionCompatibility.SameMachine;
  6614. break;
  6615. }
  6616. this.assemblyName = aName;
  6617. }
  6618. return this.assemblyName;
  6619. }
  6620. public bool Matches(string name, Version version, string culture, byte[] publicKeyToken){
  6621. if (culture != null && culture.Length == 0) culture = null;
  6622. if (this.Culture != null && this.Culture.Length == 0) this.Culture = null;
  6623. if (this.Version != version && this.Version != null && (version == null || !this.Version.Equals(version))) return false;
  6624. if (PlatformHelpers.StringCompareOrdinalIgnoreCase(this.Name, name) != 0 ||
  6625. PlatformHelpers.StringCompareOrdinalIgnoreCase(this.Culture, culture) != 0) return false;
  6626. if ((this.Flags & AssemblyFlags.Retargetable) != 0) return true;
  6627. byte[] thisToken = this.PublicKeyToken;
  6628. if (publicKeyToken == null) return thisToken == null;
  6629. if (thisToken == publicKeyToken) return true;
  6630. if (thisToken == null) return false;
  6631. int n = publicKeyToken.Length;
  6632. if (n != thisToken.Length) return false;
  6633. for (int i = 0; i < n; i++) if (thisToken[i] != publicKeyToken[i]) return false;
  6634. return true;
  6635. }
  6636. public bool MatchesIgnoringVersion(AssemblyReference reference){
  6637. if (reference == null) return false;
  6638. return this.Matches(reference.Name, this.Version, reference.Culture, reference.PublicKeyToken);
  6639. }
  6640. public byte[] PublicKeyToken{
  6641. get{
  6642. if (this.token != null) return this.token;
  6643. if (this.PublicKeyOrToken == null || this.PublicKeyOrToken.Length == 0) return null;
  6644. if (this.PublicKeyOrToken.Length == 8) return this.token = this.PublicKeyOrToken;
  6645. #if !ROTOR
  6646. System.Security.Cryptography.SHA1 sha = new System.Security.Cryptography.SHA1CryptoServiceProvider();
  6647. byte[] hashedKey = sha.ComputeHash(this.PublicKeyOrToken);
  6648. byte[] token = new byte[8];
  6649. for (int i = 0, n = hashedKey.Length-1; i < 8; i++) token[i] = hashedKey[n-i];
  6650. return this.token = token;
  6651. #else
  6652. return null;
  6653. #endif
  6654. }
  6655. }
  6656. }
  6657. public class ModuleReference : Node{
  6658. private Module module;
  6659. private string name;
  6660. public ModuleReference()
  6661. : base(NodeType.ModuleReference){
  6662. }
  6663. public ModuleReference(string name, Module module)
  6664. : base(NodeType.ModuleReference){
  6665. this.name = name;
  6666. this.module = module;
  6667. }
  6668. public Module Module {
  6669. get{return this.module;}
  6670. set{this.module = value;}
  6671. }
  6672. public string Name{
  6673. get{return this.name;}
  6674. set{this.name = value;}
  6675. }
  6676. }
  6677. /// <summary>
  6678. /// A member of a Namespace or a TypeNode
  6679. /// </summary>
  6680. public abstract class Member : Node{
  6681. #if !MinimalReader
  6682. /// <summary>The namespace of which this node is a member. Null if this node is a member of type.</summary>
  6683. public Namespace DeclaringNamespace;
  6684. /// <summary>
  6685. /// Indicates that the signature of this member may include unsafe types such as pointers. For methods and properties, it also indicates that the
  6686. /// code may contain unsafe constructions such as pointer arithmetic.
  6687. /// </summary>
  6688. public bool IsUnsafe;
  6689. /// <summary>A list of other nodes that refer to this member. Must be filled in by client code.</summary>
  6690. public NodeList References;
  6691. #endif
  6692. protected Member(NodeType nodeType)
  6693. : base(nodeType){
  6694. }
  6695. protected Member(TypeNode declaringType, AttributeList attributes, Identifier name, NodeType nodeType)
  6696. : base(nodeType){
  6697. this.attributes = attributes;
  6698. this.declaringType = declaringType;
  6699. this.name = name;
  6700. }
  6701. private TypeNode declaringType;
  6702. /// <summary>The type of which this node is a member. Null if this node is a member of a Namespace.</summary>
  6703. public TypeNode DeclaringType{
  6704. get{return this.declaringType;}
  6705. set{this.declaringType = value;}
  6706. }
  6707. private Identifier name;
  6708. /// <summary>The unqualified name of the member.</summary>
  6709. public Identifier Name {
  6710. get{return this.name;}
  6711. set{ this.name = value; }
  6712. }
  6713. #if ExtendedRuntime
  6714. private Anonymity anonymity;
  6715. #endif
  6716. protected AttributeList attributes;
  6717. private bool notObsolete;
  6718. private ObsoleteAttribute obsoleteAttribute;
  6719. /// <summary>
  6720. /// The attributes of this member. Corresponds to custom attribute annotations in C#.
  6721. /// </summary>
  6722. public virtual AttributeList Attributes{
  6723. get{
  6724. if (this.attributes != null) return this.attributes;
  6725. return this.attributes = new AttributeList();
  6726. }
  6727. set{
  6728. this.attributes = value;
  6729. }
  6730. }
  6731. protected Member hiddenMember;
  6732. public virtual Member HiddenMember{
  6733. get{
  6734. return this.hiddenMember;
  6735. }
  6736. set{
  6737. this.hiddenMember = value;
  6738. }
  6739. }
  6740. protected bool hidesBaseClassMemberSpecifiedExplicitly;
  6741. protected bool hidesBaseClassMember;
  6742. /// <summary>Indicates if this is a member of a subclass that intentionally has the same signature as a member of a base class. Corresponds to the "new" modifier in C#.</summary>
  6743. public bool HidesBaseClassMember{
  6744. get{
  6745. if (this.hidesBaseClassMemberSpecifiedExplicitly)
  6746. return this.hidesBaseClassMember;
  6747. else
  6748. return this.HiddenMember != null;
  6749. }
  6750. set{
  6751. this.hidesBaseClassMember = value;
  6752. this.hidesBaseClassMemberSpecifiedExplicitly = true;
  6753. }
  6754. }
  6755. protected Member overriddenMember;
  6756. public virtual Member OverriddenMember{
  6757. get{
  6758. return this.overriddenMember;
  6759. }
  6760. set{
  6761. this.overriddenMember = value;
  6762. }
  6763. }
  6764. protected bool overridesBaseClassMemberSpecifiedExplicitly;
  6765. protected bool overridesBaseClassMember;
  6766. /// <summary>Indicates if this is a virtual method of a subclass that intentionally overrides a method of a base class. Corresponds to the "override" modifier in C#.</summary>
  6767. public virtual bool OverridesBaseClassMember{
  6768. get{
  6769. if (this.overridesBaseClassMemberSpecifiedExplicitly)
  6770. return this.overridesBaseClassMember;
  6771. else
  6772. return this.OverriddenMember != null;
  6773. }
  6774. set{
  6775. this.overridesBaseClassMember = value;
  6776. this.overridesBaseClassMemberSpecifiedExplicitly = true;
  6777. }
  6778. }
  6779. /// <summary>
  6780. /// Gets the first attribute of the given type in the attribute list of this member. Returns null if none found.
  6781. /// This should not be called until the AST containing this member has been processed to replace symbolic references
  6782. /// to members with references to the actual members.
  6783. /// </summary>
  6784. public virtual AttributeNode GetAttribute(TypeNode attributeType) {
  6785. if (attributeType == null) return null;
  6786. AttributeList attributes = this.Attributes;
  6787. for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++) {
  6788. AttributeNode attr = attributes[i];
  6789. if (attr == null) continue;
  6790. MemberBinding mb = attr.Constructor as MemberBinding;
  6791. if (mb != null) {
  6792. if (mb.BoundMember == null) continue;
  6793. if (mb.BoundMember.DeclaringType != attributeType) continue;
  6794. return attr;
  6795. }
  6796. Literal lit = attr.Constructor as Literal;
  6797. if (lit == null) continue;
  6798. if ((lit.Value as TypeNode) != attributeType) continue;
  6799. return attr;
  6800. }
  6801. return null;
  6802. }
  6803. public virtual AttributeList GetFilteredAttributes(TypeNode attributeType){
  6804. if (attributeType == null) return this.Attributes;
  6805. AttributeList attributes = this.Attributes;
  6806. AttributeList filtered = new AttributeList();
  6807. for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++) {
  6808. AttributeNode attr = attributes[i];
  6809. if (attr == null) continue;
  6810. MemberBinding mb = attr.Constructor as MemberBinding;
  6811. if (mb != null) {
  6812. if (mb.BoundMember != null && mb.BoundMember.DeclaringType == attributeType) continue;
  6813. filtered.Add(attr);
  6814. continue;
  6815. }
  6816. Literal lit = attr.Constructor as Literal;
  6817. if (lit != null && (lit.Value as TypeNode) == attributeType) continue;
  6818. filtered.Add(attr);
  6819. }
  6820. return filtered;
  6821. }
  6822. #if ExtendedRuntime
  6823. public virtual AttributeList GetAllAttributes(TypeNode attributeType)
  6824. {
  6825. AttributeList filtered = new AttributeList();
  6826. if (attributeType == null) return filtered;
  6827. AttributeList attributes = this.Attributes;
  6828. for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++) {
  6829. AttributeNode attr = attributes[i];
  6830. if (attr == null) continue;
  6831. MemberBinding mb = attr.Constructor as MemberBinding;
  6832. if (mb != null) {
  6833. if (mb.BoundMember != null && mb.BoundMember.DeclaringType == attributeType)
  6834. filtered.Add(attr);
  6835. continue;
  6836. }
  6837. Literal lit = attr.Constructor as Literal;
  6838. if (lit != null && (lit.Value as TypeNode) == attributeType)
  6839. filtered.Add(attr);
  6840. }
  6841. return filtered;
  6842. }
  6843. /// <summary>
  6844. /// If this is true, the name of the member is meaningless and the member is intended as an "invisible" container for other members.
  6845. /// The value of this property is controlled by the presence or absence of the Anonymous attribute.
  6846. /// </summary>
  6847. public bool IsAnonymous{
  6848. get{
  6849. switch (this.Anonymity){
  6850. case Anonymity.None:
  6851. case Anonymity.Unknown:
  6852. return false;
  6853. default:
  6854. return true;
  6855. }
  6856. }
  6857. }
  6858. /// <summary>
  6859. /// Exposes the value of the Anonymous attribute. The value is Anonimity.None if no attribute is present.
  6860. /// </summary>
  6861. public Anonymity Anonymity{
  6862. get{
  6863. if (this.anonymity == Anonymity.Unknown){
  6864. AttributeNode attr = this.GetAttribute(SystemTypes.AnonymousAttribute);
  6865. if (attr == null)
  6866. this.anonymity = Anonymity.None;
  6867. else{
  6868. this.anonymity = Anonymity.Structural; // default
  6869. if (attr.Expressions != null){
  6870. for (int i = 0, n = attr.Expressions.Count; i < n; i++){
  6871. NamedArgument na = attr.Expressions[i] as NamedArgument;
  6872. if (na == null || na.Name != null) continue;
  6873. if (na.Name.UniqueIdKey == StandardIds.Anonymity.UniqueIdKey){
  6874. Literal lit = na.Value as Literal;
  6875. if (lit == null) continue;
  6876. this.anonymity = (Anonymity)lit.Value;
  6877. break;
  6878. }
  6879. }
  6880. }
  6881. }
  6882. }
  6883. return this.anonymity;
  6884. }
  6885. }
  6886. CciMemberKind cciKind;
  6887. public CciMemberKind CciKind{
  6888. get{
  6889. if (cciKind == CciMemberKind.Unknown){
  6890. AttributeNode a = GetAttribute(SystemTypes.CciMemberKindAttribute);
  6891. if (a == null)
  6892. cciKind = CciMemberKind.Regular;
  6893. else
  6894. cciKind = (CciMemberKind) ((Literal) a.Expressions[0]).Value;
  6895. }
  6896. return cciKind;
  6897. }
  6898. set{
  6899. this.cciKind = value;
  6900. }
  6901. }
  6902. #endif
  6903. /// <summary>
  6904. /// The concatenation of the FullName of the containing member and the name of this member.
  6905. /// Separated with a '.' character if the containing member is a namespace and a '+' character if the containing member is a Type.
  6906. /// Includes the parameter type full names when this member is a method or a property. Also includes (generic) template arguments.
  6907. /// </summary>
  6908. public abstract string/*!*/ FullName { get;}
  6909. /// <summary>True if all references to this member must be from the assembly containing the definition of this member. </summary>
  6910. public abstract bool IsAssembly{get;}
  6911. /// <summary>
  6912. /// True if access to this member is controlled by the compiler and not the runtime. Cannot be accessed from other assemblies since these
  6913. /// are not necessarily controlled by the same compiler.
  6914. /// </summary>
  6915. public abstract bool IsCompilerControlled{get;}
  6916. /// <summary>True if this member can only be accessed from subclasses of the class declaring this member.</summary>
  6917. public abstract bool IsFamily{get;}
  6918. /// <summary>True if this member can only be accessed from subclasses of the class declaring this member, provided that these subclasses are also
  6919. /// contained in the assembly containing this member.</summary>
  6920. public abstract bool IsFamilyAndAssembly{get;}
  6921. /// <summary>True if all references to this member must either be from the assembly containing the definition of this member,
  6922. /// or from a subclass of the class declaring this member.</summary>
  6923. public abstract bool IsFamilyOrAssembly{get;}
  6924. /// <summary>True if all references to this member must be from members of the type declaring this member./// </summary>
  6925. public abstract bool IsPrivate{get;}
  6926. /// <summary>True if the member can be accessed from anywhere./// </summary>
  6927. public abstract bool IsPublic{get;}
  6928. /// <summary>True if the name of this member conforms to a naming pattern with special meaning. For example the name of a property getter.</summary>
  6929. public abstract bool IsSpecialName{get;}
  6930. /// <summary>True if this member always has the same value or behavior for all instances the declaring type.</summary>
  6931. public abstract bool IsStatic{get;}
  6932. /// <summary>True if another assembly can contain a reference to this member.</summary>
  6933. public abstract bool IsVisibleOutsideAssembly{get;}
  6934. /// <summary>A cached reference to the first Obsolete attribute of this member. Null if no such attribute exsits.</summary>
  6935. public ObsoleteAttribute ObsoleteAttribute{
  6936. get{
  6937. if (this.notObsolete) return null;
  6938. if (this.obsoleteAttribute == null){
  6939. AttributeNode attr = this.GetAttribute(SystemTypes.ObsoleteAttribute);
  6940. if (attr != null){
  6941. ExpressionList args = attr.Expressions;
  6942. int numArgs = args == null ? 0 : args.Count;
  6943. Literal lit0 = numArgs > 0 ? args[0] as Literal : null;
  6944. Literal lit1 = numArgs > 1 ? args[1] as Literal : null;
  6945. string message = lit0 != null ? lit0.Value as string : null;
  6946. object isError = lit1 != null ? lit1.Value : null;
  6947. if (isError is bool)
  6948. return this.obsoleteAttribute = new ObsoleteAttribute(message, (bool)isError);
  6949. else
  6950. return this.obsoleteAttribute = new ObsoleteAttribute(message);
  6951. }
  6952. this.notObsolete = true;
  6953. }
  6954. return this.obsoleteAttribute;
  6955. }
  6956. set{
  6957. this.obsoleteAttribute = value;
  6958. this.notObsolete = false;
  6959. }
  6960. }
  6961. #if !MinimalReader
  6962. /// <summary>The source code, if any, corresponding to the value in Documentation.</summary>
  6963. public Node DocumentationNode;
  6964. #endif
  6965. #if !NoXml
  6966. protected XmlNode documentation;
  6967. /// <summary>The body of an XML element containing a description of this member. Used to associated documentation (such as this comment) with members.
  6968. /// The fragment usually conforms to the structure defined in the C# standard.</summary>
  6969. public virtual XmlNode Documentation{
  6970. get{
  6971. XmlNode documentation = this.documentation;
  6972. if (documentation != null) return documentation;
  6973. TypeNode t = this.DeclaringType;
  6974. if (t == null) t = this as TypeNode;
  6975. Module m = t == null ? null : t.DeclaringModule;
  6976. TrivialHashtable cache = m == null ? null : m.GetMemberDocumentationCache();
  6977. if (cache == null) return null;
  6978. return this.documentation = (XmlNode)cache[this.DocumentationId.UniqueIdKey];
  6979. }
  6980. set{
  6981. this.documentation = value;
  6982. }
  6983. }
  6984. protected Identifier documentationId;
  6985. protected virtual Identifier GetDocumentationId(){
  6986. return Identifier.Empty;
  6987. }
  6988. /// <summary>
  6989. /// The value of the name attribute of the XML element whose body is the XML fragment returned by Documentation.
  6990. /// </summary>
  6991. public Identifier DocumentationId{
  6992. get{
  6993. Identifier documentationId = this.documentationId;
  6994. if (documentationId != null) return documentationId;
  6995. return this.DocumentationId = this.GetDocumentationId();
  6996. }
  6997. set{
  6998. this.documentationId = value;
  6999. }
  7000. }
  7001. protected string helpText;
  7002. /// <summary>
  7003. /// The value of the summary child element of the XML fragment returned by Documentation. All markup is stripped from the value.
  7004. /// </summary>
  7005. public virtual string HelpText{
  7006. get{
  7007. string helpText = this.helpText;
  7008. if (helpText != null) return helpText;
  7009. XmlNode documentation = this.Documentation;
  7010. if (documentation != null && documentation.HasChildNodes){
  7011. //^ assume documentation.ChildNodes != null;
  7012. foreach (XmlNode child in documentation.ChildNodes)
  7013. if (child.Name == "summary")
  7014. return this.helpText = this.GetHelpText(child);
  7015. }
  7016. return this.helpText = "";
  7017. }
  7018. set{
  7019. this.helpText = value;
  7020. }
  7021. }
  7022. public virtual string GetParameterHelpText(string parameterName){
  7023. XmlNode documentation = this.Documentation;
  7024. if (documentation == null || documentation.ChildNodes == null) return null;
  7025. foreach (XmlNode cdoc in documentation.ChildNodes){
  7026. if (cdoc == null) continue;
  7027. if (cdoc.Name != "param") continue;
  7028. if (cdoc.Attributes == null) continue;
  7029. foreach (XmlAttribute attr in cdoc.Attributes){
  7030. if (attr == null || attr.Name != "name" || attr.Value != parameterName) continue;
  7031. if (!cdoc.HasChildNodes) continue;
  7032. return this.GetHelpText(cdoc);
  7033. }
  7034. }
  7035. return null;
  7036. }
  7037. private string GetHelpText(XmlNode node){
  7038. if (node == null) return "";
  7039. StringBuilder sb = new StringBuilder();
  7040. if (node.HasChildNodes){
  7041. foreach (XmlNode child in node.ChildNodes){
  7042. switch (child.NodeType){
  7043. case XmlNodeType.Element:
  7044. string str = this.GetHelpText(child);
  7045. if (str == null || str.Length == 0) continue;
  7046. if (sb.Length > 0 && !Char.IsPunctuation(str[0]))
  7047. sb.Append(' ');
  7048. sb.Append(str);
  7049. break;
  7050. case XmlNodeType.CDATA:
  7051. case XmlNodeType.Entity:
  7052. case XmlNodeType.Text:
  7053. this.AppendValue(sb, child);
  7054. break;
  7055. }
  7056. }
  7057. }else if (node.Attributes != null){
  7058. foreach (XmlAttribute attr in node.Attributes){
  7059. this.AppendValue(sb, attr);
  7060. }
  7061. }
  7062. return sb.ToString();
  7063. }
  7064. private int filterPriority;
  7065. public virtual System.ComponentModel.EditorBrowsableState FilterPriority {
  7066. get {
  7067. if (this.filterPriority > 0) return (System.ComponentModel.EditorBrowsableState)(this.filterPriority-1);
  7068. int prio = 0;
  7069. XmlNode documentation = this.Documentation;
  7070. if (documentation != null && documentation.HasChildNodes) {
  7071. foreach (XmlNode child in documentation.ChildNodes)
  7072. if (child.Name == "filterpriority") {
  7073. PlatformHelpers.TryParseInt32(child.InnerText, out prio);
  7074. switch (prio) {
  7075. case 2: this.filterPriority = (int)System.ComponentModel.EditorBrowsableState.Advanced; break;
  7076. case 3: this.filterPriority = (int)System.ComponentModel.EditorBrowsableState.Never; break;
  7077. default: this.filterPriority = (int)System.ComponentModel.EditorBrowsableState.Always; break;
  7078. }
  7079. this.filterPriority++;
  7080. return (System.ComponentModel.EditorBrowsableState)(this.filterPriority - 1);
  7081. }
  7082. }
  7083. AttributeList attributes = this.Attributes;
  7084. for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++){
  7085. //^ assert attributes != null;
  7086. AttributeNode attr = attributes[i];
  7087. if (attr == null || attr.Type == null) continue;
  7088. if (attr.Expressions == null || attr.Expressions.Count < 1) continue;
  7089. if (attr.Type.FullName != "System.ComponentModel.EditorBrowsableAttribute") continue;
  7090. Literal lit = attr.Expressions[0] as Literal;
  7091. if (lit == null || !(lit.Value is int)) continue;
  7092. //^ assert lit.Value != null;
  7093. prio = (int)lit.Value;
  7094. return (System.ComponentModel.EditorBrowsableState)((this.filterPriority = prio+1) - 1);
  7095. }
  7096. return (System.ComponentModel.EditorBrowsableState)((this.filterPriority = 1) - 1);
  7097. }
  7098. set {
  7099. this.filterPriority = ((int)value)+1;
  7100. }
  7101. }
  7102. /// <summary>
  7103. /// Writes out an element with tag "element", name attribute DocumentationId.ToString() and body Documentation using the provided XmlTextWriter instance.
  7104. /// </summary>
  7105. public virtual void WriteDocumentation(XmlTextWriter xwriter){
  7106. if (this.documentation == null || xwriter == null) return;
  7107. xwriter.WriteStartElement("member");
  7108. if (this.DocumentationId == null) return;
  7109. xwriter.WriteAttributeString("name", this.DocumentationId.ToString());
  7110. this.documentation.WriteContentTo(xwriter);
  7111. xwriter.WriteEndElement();
  7112. }
  7113. private readonly static char[]/*!*/ tags = {'E', 'F', 'M', 'P', 'T'};
  7114. private void AppendValue(StringBuilder/*!*/ sb, XmlNode/*!*/ node) {
  7115. string str = node.Value;
  7116. if (str != null){
  7117. str = str.Trim();
  7118. if (str.Length > 2 && str[1] == ':' && str.LastIndexOfAny(tags, 0, 1) == 0){
  7119. char tag = str[0];
  7120. str = str.Substring(2);
  7121. if (tag == 'T' && str.IndexOf(TargetPlatform.GenericTypeNamesMangleChar) >= 0) {
  7122. Module mod = null;
  7123. if (this.DeclaringType != null)
  7124. mod = this.DeclaringType.DeclaringModule;
  7125. else if (this is TypeNode)
  7126. mod = ((TypeNode)this).DeclaringModule;
  7127. if (mod != null){
  7128. Identifier ns;
  7129. Identifier tn;
  7130. int i = str.LastIndexOf('.');
  7131. if (i < 0 || i >= str.Length){
  7132. ns = Identifier.Empty;
  7133. tn = Identifier.For(str);
  7134. }else{
  7135. ns = Identifier.For(str.Substring(0, i));
  7136. tn = Identifier.For(str.Substring(i + 1));
  7137. }
  7138. TypeNode t = mod.GetType(ns, tn, true);
  7139. if (t != null) str = t.GetFullUnmangledNameWithTypeParameters();
  7140. }
  7141. }
  7142. }
  7143. if (str == null || str.Length == 0) return;
  7144. bool lastCharWasSpace = false;
  7145. if (sb.Length > 0 && !Char.IsPunctuation(str[0]) && !Char.IsWhiteSpace(str[0])){
  7146. sb.Append(' ');
  7147. lastCharWasSpace = true;
  7148. }
  7149. foreach (char ch in str){
  7150. if (Char.IsWhiteSpace(ch)){
  7151. if (lastCharWasSpace) continue;
  7152. lastCharWasSpace = true;
  7153. sb.Append(' ');
  7154. }else{
  7155. lastCharWasSpace = false;
  7156. sb.Append(ch);
  7157. }
  7158. }
  7159. if (sb.Length > 0 && Char.IsWhiteSpace(sb[sb.Length-1]))
  7160. sb.Length -= 1;
  7161. }
  7162. }
  7163. #endif
  7164. #if FxCop
  7165. internal string GetName(MemberFormat options)
  7166. {
  7167. StringBuilder name = new StringBuilder();
  7168. GetName(options, name);
  7169. return name.ToString();
  7170. }
  7171. internal virtual void GetName(MemberFormat options, StringBuilder name)
  7172. {
  7173. if (options.Type.TypeName != TypeNameFormat.None && this.DeclaringType != null)
  7174. {
  7175. this.DeclaringType.GetName(options, name);
  7176. name.Append('.');
  7177. }
  7178. name.Append(this.Name.Name);
  7179. }
  7180. #endif
  7181. }
  7182. #if !MinimalReader
  7183. public class TypeMemberSnippet : Member{
  7184. public IParserFactory ParserFactory;
  7185. public TypeMemberSnippet()
  7186. : base(NodeType.TypeMemberSnippet){
  7187. }
  7188. public TypeMemberSnippet(IParserFactory parserFactory, SourceContext sctx)
  7189. : base(NodeType.TypeMemberSnippet){
  7190. this.ParserFactory = parserFactory;
  7191. this.SourceContext = sctx;
  7192. }
  7193. public override string/*!*/ FullName {
  7194. get{throw new InvalidOperationException();}
  7195. }
  7196. public override bool IsCompilerControlled{
  7197. get{throw new InvalidOperationException();}
  7198. }
  7199. public override bool IsAssembly{
  7200. get{throw new InvalidOperationException();}
  7201. }
  7202. public override bool IsFamily{
  7203. get{throw new InvalidOperationException();}
  7204. }
  7205. public override bool IsFamilyAndAssembly{
  7206. get{throw new InvalidOperationException();}
  7207. }
  7208. public override bool IsFamilyOrAssembly{
  7209. get{throw new InvalidOperationException();}
  7210. }
  7211. public override bool IsPrivate{
  7212. get{throw new InvalidOperationException();}
  7213. }
  7214. public override bool IsPublic{
  7215. get{throw new InvalidOperationException();}
  7216. }
  7217. public override bool IsSpecialName{
  7218. get{throw new InvalidOperationException();}
  7219. }
  7220. public override bool IsStatic{
  7221. get{throw new InvalidOperationException();}
  7222. }
  7223. public override bool IsVisibleOutsideAssembly {
  7224. get{throw new InvalidOperationException();}
  7225. }
  7226. }
  7227. #endif
  7228. /// <summary>
  7229. /// The common base class for all types. This type should not be extended directly.
  7230. /// Instead extend one of the standard subclasses such as Class, Struct or Interface, since in
  7231. /// the CLR a type has to be an instance of one the subclasses, and a type which does not extend
  7232. /// one of these types will have no equivalent in the CLR.
  7233. /// </summary>
  7234. public abstract class TypeNode : Member
  7235. #if ExtendedRuntime
  7236. , IEquatable<TypeNode>
  7237. #endif
  7238. {
  7239. #if ExtendedRuntime
  7240. /// <summary>The invariants and modelfield contracts associated with this type (for now only classes, interfaces, structs).</summary>
  7241. public TypeContract Contract;
  7242. #endif
  7243. private int classSize;
  7244. /// <summary>Specifies the total size in bytes of instances of types with prescribed layout.</summary>
  7245. public int ClassSize{
  7246. get{return this.classSize;}
  7247. set{this.classSize = value;}
  7248. }
  7249. private Module declaringModule;
  7250. /// <summary>The module or assembly to which the compiled type belongs.</summary>
  7251. public Module DeclaringModule{
  7252. get{return this.declaringModule;}
  7253. set{this.declaringModule = value;}
  7254. }
  7255. private TypeFlags flags;
  7256. public TypeFlags Flags{
  7257. get{return this.flags;}
  7258. set{this.flags = value;}
  7259. }
  7260. /// <summary>The interfaces implemented by this class or struct, or the extended by this interface.</summary>
  7261. public virtual InterfaceList Interfaces {
  7262. get { if (this.interfaces == null) { this.interfaces = new InterfaceList(0);} return this.interfaces; }
  7263. set { this.interfaces = value; }
  7264. }
  7265. protected InterfaceList interfaces;
  7266. #if !MinimalReader
  7267. public InterfaceList InterfaceExpressions;
  7268. #endif
  7269. private Identifier @namespace;
  7270. /// <summary>The namespace to which this type belongs. Null if the type is nested inside another type.</summary>
  7271. public Identifier Namespace{
  7272. get{return this.@namespace;}
  7273. set{this.@namespace = value;}
  7274. }
  7275. private int packingSize;
  7276. /// <summary>Specifies the alignment of fields within types with prescribed layout.</summary>
  7277. public int PackingSize{
  7278. get{return this.packingSize;}
  7279. set{this.packingSize = value;}
  7280. }
  7281. #if !MinimalReader
  7282. /// <summary>If this type is the combined result of a number of partial type definitions, this lists the partial definitions.</summary>
  7283. public TypeNodeList IsDefinedBy;
  7284. #endif
  7285. /// <summary>
  7286. /// True if this type is the result of a template instantiation with arguments that are themselves template parameters.
  7287. /// Used to model template instantiations occurring inside templates.
  7288. /// </summary>
  7289. public bool IsNotFullySpecialized;
  7290. public bool NewTemplateInstanceIsRecursive;
  7291. #if !MinimalReader
  7292. /// <summary>
  7293. /// If this type is a partial definition, the value of this is the combined type resulting from all the partial definitions.
  7294. /// </summary>
  7295. public TypeNode PartiallyDefines;
  7296. /// <summary>
  7297. /// The list of extensions of this type, if it's a non-extension type.
  7298. /// all extensions implement the IExtendTypeNode interface (in the Sing# code base).
  7299. /// null = empty list
  7300. /// </summary>
  7301. private TypeNodeList extensions = null;
  7302. /// <summary>
  7303. /// Whether or not the list of extensions has been examined;
  7304. /// it's a bug to record a new extension after extensions have been examined.
  7305. /// </summary>
  7306. private bool extensionsExamined = false;
  7307. /// <summary>
  7308. /// Record another extension of this type.
  7309. /// </summary>
  7310. /// <param name="extension"></param>
  7311. public void RecordExtension(TypeNode extension) {
  7312. Debug.Assert(!extensionsExamined, "adding an extension after they've already been examined");
  7313. if (this.extensions == null) this.extensions = new TypeNodeList();
  7314. this.extensions.Add(extension);
  7315. }
  7316. /// <summary>
  7317. /// The property that should be accessed by clients to get the list of extensions of this type.
  7318. /// </summary>
  7319. public TypeNodeList Extensions {
  7320. get {
  7321. this.extensionsExamined = true;
  7322. return this.extensions;
  7323. }
  7324. set {
  7325. Debug.Assert(!extensionsExamined, "setting extensions after they've already been examined");
  7326. this.extensions = value;
  7327. }
  7328. }
  7329. /// <summary>
  7330. /// When duplicating a type node, we want to transfer the extensions and the extensionsExamined flag without
  7331. /// treating this as a "touch" that sets the examined flag. Pretty ugly, though.
  7332. /// </summary>
  7333. public TypeNodeList ExtensionsNoTouch{
  7334. get{ return this.extensions; }
  7335. }
  7336. /// <summary>
  7337. /// Copy a (possibly transformed) set of extensions from source to the
  7338. /// receiver, including whether or not the extensions have been examined.
  7339. /// </summary>
  7340. public void DuplicateExtensions(TypeNode source, TypeNodeList newExtensions){
  7341. if (source == null) return;
  7342. this.extensions = newExtensions;
  7343. this.extensionsExamined = source.extensionsExamined;
  7344. }
  7345. /// <summary>
  7346. /// If the receiver is a type extension, return the extendee, otherwise return the receiver.
  7347. /// [The identity function, except for dialects (e.g. Extensible Sing#) that allow
  7348. /// extensions and differing views of types]
  7349. /// </summary>
  7350. public virtual TypeNode/*!*/ EffectiveTypeNode{
  7351. get{
  7352. return this;
  7353. }
  7354. }
  7355. /// <summary>
  7356. /// Return whether t1 represents the same type as t2 (or both are null).
  7357. /// This copes with the cases where t1 and/or t2 may be type views and/or type extensions, as
  7358. /// in Extensible Sing#.
  7359. /// </summary>
  7360. public static bool operator ==(TypeNode t1, TypeNode t2){
  7361. return
  7362. (object)t1 == null ?
  7363. (object)t2 == null :
  7364. (object)t2 != null && (object)t1.EffectiveTypeNode == (object)t2.EffectiveTypeNode;
  7365. }
  7366. // modify the other operations related to equality
  7367. public static bool operator !=(TypeNode t1, TypeNode t2){
  7368. return !(t1 == t2);
  7369. }
  7370. public override bool Equals(Object other){
  7371. return this == (other as TypeNode);
  7372. }
  7373. #if ExtendedRuntime
  7374. public bool Equals(TypeNode other)
  7375. {
  7376. return this == other;
  7377. }
  7378. #endif
  7379. public override int GetHashCode(){
  7380. TypeNode tn = this.EffectiveTypeNode;
  7381. if ((object)tn == (object)this){
  7382. return base.GetHashCode();
  7383. } else {
  7384. return tn.GetHashCode();
  7385. }
  7386. }
  7387. #endif
  7388. /// <summary>
  7389. /// A delegate that is called the first time Members is accessed, if non-null.
  7390. /// Provides for incremental construction of the type node.
  7391. /// Must not leave Members null.
  7392. /// </summary>
  7393. public TypeMemberProvider ProvideTypeMembers;
  7394. /// <summary>
  7395. /// The type of delegates that fill in the Members property of the given type.
  7396. /// </summary>
  7397. public delegate void TypeMemberProvider(TypeNode/*!*/ type, object/*!*/ handle);
  7398. /// <summary>
  7399. /// A delegate that is called the first time NestedTypes is accessed, if non-null.
  7400. /// </summary>
  7401. public NestedTypeProvider ProvideNestedTypes;
  7402. /// <summary>
  7403. /// The type of delegates that fill in the NestedTypes property of the given type.
  7404. /// </summary>
  7405. public delegate void NestedTypeProvider(TypeNode/*!*/ type, object/*!*/ handle);
  7406. /// <summary>
  7407. /// A delegate that is called the first time Attributes is accessed, if non-null.
  7408. /// Provides for incremental construction of the type node.
  7409. /// Must not leave Attributes null.
  7410. /// </summary>
  7411. public TypeAttributeProvider ProvideTypeAttributes;
  7412. /// <summary>
  7413. /// The type of delegates that fill in the Attributes property of the given type.
  7414. /// </summary>
  7415. public delegate void TypeAttributeProvider(TypeNode/*!*/ type, object/*!*/ handle);
  7416. /// <summary>
  7417. /// Opaque information passed as a parameter to the delegates in ProvideTypeMembers et al.
  7418. /// Typically used to associate this namespace instance with a helper object.
  7419. /// </summary>
  7420. public object ProviderHandle;
  7421. private TypeNodeList templateInstances;
  7422. /// <summary>Contains all the types instantiated from this non generic template type.</summary>
  7423. public TypeNodeList TemplateInstances{
  7424. get{return this.templateInstances;}
  7425. set{this.templateInstances = value;}
  7426. }
  7427. internal TypeNode(NodeType nodeType)
  7428. : base(nodeType){
  7429. #if ExtendedRuntime
  7430. this.Contract = new TypeContract(this, true);
  7431. #endif
  7432. }
  7433. internal TypeNode(NodeType nodeType, NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  7434. : base(nodeType){
  7435. this.ProvideNestedTypes = provideNestedTypes;
  7436. this.ProvideTypeAttributes = provideAttributes;
  7437. this.ProvideTypeMembers = provideMembers;
  7438. this.ProviderHandle = handle;
  7439. #if !MinimalReader
  7440. this.isNormalized = true;
  7441. #endif
  7442. #if ExtendedRuntime
  7443. this.Contract = new TypeContract(this);
  7444. #endif
  7445. }
  7446. internal TypeNode(Module declaringModule, TypeNode declaringType, AttributeList attributes, TypeFlags flags,
  7447. Identifier Namespace, Identifier name, InterfaceList interfaces, MemberList members, NodeType nodeType)
  7448. : base(null, attributes, name, nodeType){
  7449. this.DeclaringModule = declaringModule;
  7450. this.DeclaringType = declaringType;
  7451. this.Flags = flags;
  7452. this.Interfaces = interfaces;
  7453. this.members = members;
  7454. this.Namespace = Namespace;
  7455. #if ExtendedRuntime
  7456. this.Contract = new TypeContract(this, true);
  7457. #endif
  7458. }
  7459. public override AttributeList Attributes{
  7460. get{
  7461. if (this.attributes == null){
  7462. if (this.ProvideTypeAttributes != null && this.ProviderHandle != null){
  7463. lock (Module.GlobalLock){
  7464. if (this.attributes == null)
  7465. this.ProvideTypeAttributes(this, this.ProviderHandle);
  7466. }
  7467. }else
  7468. this.attributes = new AttributeList(0);
  7469. }
  7470. return this.attributes;
  7471. }
  7472. set{
  7473. this.attributes = value;
  7474. }
  7475. }
  7476. protected SecurityAttributeList securityAttributes;
  7477. /// <summary>Contains declarative security information associated with the type.</summary>
  7478. public SecurityAttributeList SecurityAttributes{
  7479. get{
  7480. if (this.securityAttributes != null) return this.securityAttributes;
  7481. if (this.attributes == null){
  7482. AttributeList al = this.Attributes; //Getting the type attributes also gets the security attributes, in the case of a type that was read in by the Reader
  7483. if (al != null) al = null;
  7484. if (this.securityAttributes != null) return this.securityAttributes;
  7485. }
  7486. return this.securityAttributes = new SecurityAttributeList(0);
  7487. }
  7488. set{
  7489. this.securityAttributes = value;
  7490. }
  7491. }
  7492. /// <summary>The type from which this type is derived. Null in the case of interfaces and System.Object.</summary>
  7493. public virtual TypeNode BaseType{
  7494. get{
  7495. switch(this.NodeType){
  7496. case NodeType.ArrayType: return CoreSystemTypes.Array;
  7497. case NodeType.ClassParameter:
  7498. case NodeType.Class: return ((Class)this).BaseClass;
  7499. case NodeType.DelegateNode: return CoreSystemTypes.MulticastDelegate;
  7500. case NodeType.EnumNode: return CoreSystemTypes.Enum;
  7501. case NodeType.Struct:
  7502. #if !MinimalReader
  7503. case NodeType.TupleType:
  7504. case NodeType.TypeAlias:
  7505. case NodeType.TypeIntersection:
  7506. case NodeType.TypeUnion:
  7507. #endif
  7508. return CoreSystemTypes.ValueType;
  7509. default: return null;
  7510. }
  7511. }
  7512. }
  7513. protected internal MemberList defaultMembers;
  7514. /// <summary>A list of any members of this type that have the DefaultMember attribute.</summary>
  7515. public virtual MemberList DefaultMembers{
  7516. get{
  7517. int n = this.Members.Count;
  7518. if (n != this.memberCount){
  7519. this.UpdateMemberTable(n);
  7520. this.defaultMembers = null;
  7521. }
  7522. if (this.defaultMembers == null){
  7523. AttributeList attrs = this.Attributes;
  7524. Identifier defMemName = null;
  7525. for (int j = 0, m = attrs == null ? 0 : attrs.Count; j < m; j++){
  7526. //^ assert attrs != null;
  7527. AttributeNode attr = attrs[j];
  7528. if (attr == null) continue;
  7529. MemberBinding mb = attr.Constructor as MemberBinding;
  7530. if (mb != null && mb.BoundMember != null && mb.BoundMember.DeclaringType == SystemTypes.DefaultMemberAttribute){
  7531. if (attr.Expressions != null && attr.Expressions.Count > 0){
  7532. Literal lit = attr.Expressions[0] as Literal;
  7533. if (lit != null && lit.Value is string)
  7534. defMemName = Identifier.For((string)lit.Value);
  7535. }
  7536. break;
  7537. }
  7538. Literal litc = attr.Constructor as Literal;
  7539. if (litc != null && (litc.Value as TypeNode) == SystemTypes.DefaultMemberAttribute){
  7540. if (attr.Expressions != null && attr.Expressions.Count > 0){
  7541. Literal lit = attr.Expressions[0] as Literal;
  7542. if (lit != null && lit.Value is string)
  7543. defMemName = Identifier.For((string)lit.Value);
  7544. }
  7545. break;
  7546. }
  7547. }
  7548. if (defMemName != null)
  7549. this.defaultMembers = this.GetMembersNamed(defMemName);
  7550. else
  7551. this.defaultMembers = new MemberList(0);
  7552. }
  7553. return this.defaultMembers;
  7554. }
  7555. set{
  7556. this.defaultMembers = value;
  7557. }
  7558. }
  7559. protected string fullName;
  7560. public override string/*!*/ FullName {
  7561. get{
  7562. if (this.fullName != null) return this.fullName;
  7563. if (this.DeclaringType != null)
  7564. return this.fullName = this.DeclaringType.FullName+"+"+(this.Name == null ? "" : this.Name.ToString());
  7565. else if (this.Namespace != null && this.Namespace.UniqueIdKey != Identifier.Empty.UniqueIdKey)
  7566. return this.fullName = this.Namespace.ToString()+"."+(this.Name == null ? "" : this.Name.ToString());
  7567. else if (this.Name != null)
  7568. return this.fullName = this.Name.ToString();
  7569. else
  7570. return this.fullName = "";
  7571. }
  7572. }
  7573. #if !MinimalReader
  7574. // the same as FullName, except for dialects like Sing# with type extensions where names of
  7575. // type extensions may get mangled; in that case, this reports the name of the effective type node.
  7576. public virtual string FullNameDuringParsing {
  7577. get{ return this.FullName; }
  7578. }
  7579. #endif
  7580. public virtual string GetFullUnmangledNameWithoutTypeParameters(){
  7581. if (this.DeclaringType != null)
  7582. return this.DeclaringType.GetFullUnmangledNameWithoutTypeParameters()+"+"+this.GetUnmangledNameWithoutTypeParameters();
  7583. else if (this.Namespace != null && this.Namespace.UniqueIdKey != Identifier.Empty.UniqueIdKey)
  7584. return this.Namespace.ToString()+"."+this.GetUnmangledNameWithoutTypeParameters();
  7585. else
  7586. return this.GetUnmangledNameWithoutTypeParameters();
  7587. }
  7588. public virtual string GetFullUnmangledNameWithTypeParameters(){
  7589. if (this.DeclaringType != null)
  7590. return this.DeclaringType.GetFullUnmangledNameWithTypeParameters()+"+"+this.GetUnmangledNameWithTypeParameters(true);
  7591. else if (this.Namespace != null && this.Namespace.UniqueIdKey != Identifier.Empty.UniqueIdKey)
  7592. return this.Namespace.ToString()+"."+this.GetUnmangledNameWithTypeParameters(true);
  7593. else
  7594. return this.GetUnmangledNameWithTypeParameters(true);
  7595. }
  7596. public virtual string GetUnmangledNameWithTypeParameters(){
  7597. return this.GetUnmangledNameWithTypeParameters(false);
  7598. }
  7599. private string GetUnmangledNameWithTypeParameters(bool fullNamesForTypeParameters){
  7600. StringBuilder sb = new StringBuilder(this.GetUnmangledNameWithoutTypeParameters());
  7601. TypeNodeList templateParameters = this.TemplateParameters;
  7602. if (this.Template != null) templateParameters = this.TemplateArguments;
  7603. for (int i = 0, n = templateParameters == null ? 0 : templateParameters.Count; i < n; i++){
  7604. //^ assert templateParameters != null;
  7605. TypeNode tpar = templateParameters[i];
  7606. if (tpar == null) continue;
  7607. if (i == 0)
  7608. sb.Append('<');
  7609. else
  7610. sb.Append(',');
  7611. if (tpar.Name != null)
  7612. if (fullNamesForTypeParameters)
  7613. sb.Append(tpar.GetFullUnmangledNameWithTypeParameters());
  7614. else
  7615. sb.Append(tpar.GetUnmangledNameWithTypeParameters());
  7616. if (i == n-1)
  7617. sb.Append('>');
  7618. }
  7619. return sb.ToString();
  7620. }
  7621. protected static readonly char[]/*!*/ MangleChars = new char[]{'!', '>'};
  7622. public virtual string/*!*/ GetUnmangledNameWithoutTypeParameters(){
  7623. TypeNode.MangleChars[0] = TargetPlatform.GenericTypeNamesMangleChar;
  7624. if (this.Template != null) return this.Template.GetUnmangledNameWithoutTypeParameters();
  7625. if (this.Name == null) return "";
  7626. string name = this.Name.ToString();
  7627. if (this.TemplateParameters != null && this.TemplateParameters.Count > 0){
  7628. int lastMangle = name.LastIndexOfAny(TypeNode.MangleChars);
  7629. if (lastMangle >= 0){
  7630. if (name[lastMangle] == '>') lastMangle++;
  7631. return name.Substring(0, lastMangle);
  7632. }
  7633. }
  7634. return name;
  7635. }
  7636. #if !MinimalReader
  7637. public virtual string GetSerializedTypeName() {
  7638. bool isAssemblyQualified = true;
  7639. return this.GetSerializedTypeName(this, ref isAssemblyQualified);
  7640. }
  7641. string GetSerializedTypeName(TypeNode/*!*/ type, ref bool isAssemblyQualified) {
  7642. if (type == null) return null;
  7643. StringBuilder sb = new StringBuilder();
  7644. TypeModifier tMod = type as TypeModifier;
  7645. if (tMod != null)
  7646. type = tMod.ModifiedType;
  7647. ArrayType arrType = type as ArrayType;
  7648. if (arrType != null) {
  7649. type = arrType.ElementType;
  7650. bool isAssemQual = false;
  7651. this.AppendSerializedTypeName(sb, arrType.ElementType, ref isAssemQual);
  7652. if (arrType.IsSzArray())
  7653. sb.Append("[]");
  7654. else {
  7655. sb.Append('[');
  7656. if (arrType.Rank == 1) sb.Append('*');
  7657. for (int i = 1; i < arrType.Rank; i++) sb.Append(',');
  7658. sb.Append(']');
  7659. }
  7660. goto done;
  7661. }
  7662. Pointer pointer = type as Pointer;
  7663. if (pointer != null) {
  7664. type = pointer.ElementType;
  7665. bool isAssemQual = false;
  7666. this.AppendSerializedTypeName(sb, pointer.ElementType, ref isAssemQual);
  7667. sb.Append('*');
  7668. goto done;
  7669. }
  7670. Reference reference = type as Reference;
  7671. if (reference != null) {
  7672. type = reference.ElementType;
  7673. bool isAssemQual = false;
  7674. this.AppendSerializedTypeName(sb, reference.ElementType, ref isAssemQual);
  7675. sb.Append('&');
  7676. goto done;
  7677. }
  7678. if (type.Template == null)
  7679. sb.Append(type.FullName);
  7680. else {
  7681. sb.Append(type.Template.FullName);
  7682. sb.Append('[');
  7683. for (int i = 0, n = type.TemplateArguments == null ? 0 : type.TemplateArguments.Count; i < n; i++) {
  7684. //^ assert type.TemplateArguments != null;
  7685. bool isAssemQual = true;
  7686. this.AppendSerializedTypeName(sb, type.TemplateArguments[i], ref isAssemQual);
  7687. if (i < n-1) sb.Append(',');
  7688. }
  7689. sb.Append(']');
  7690. }
  7691. done:
  7692. if (isAssemblyQualified)
  7693. this.AppendAssemblyQualifierIfNecessary(sb, type, out isAssemblyQualified);
  7694. return sb.ToString();
  7695. }
  7696. void AppendAssemblyQualifierIfNecessary(StringBuilder/*!*/ sb, TypeNode type, out bool isAssemQualified) {
  7697. isAssemQualified = false;
  7698. if (type == null) return;
  7699. AssemblyNode referencedAssembly = type.DeclaringModule as AssemblyNode;
  7700. if (referencedAssembly != null) {
  7701. sb.Append(", ");
  7702. sb.Append(referencedAssembly.StrongName);
  7703. isAssemQualified = true;
  7704. }
  7705. }
  7706. void AppendSerializedTypeName(StringBuilder/*!*/ sb, TypeNode type, ref bool isAssemQualified) {
  7707. if (type == null) return;
  7708. string argTypeName = this.GetSerializedTypeName(type, ref isAssemQualified);
  7709. if (isAssemQualified) sb.Append('[');
  7710. sb.Append(argTypeName);
  7711. if (isAssemQualified) sb.Append(']');
  7712. }
  7713. #endif
  7714. /// <summary>
  7715. /// Return the name the constructor should have in this type node. By default, it's
  7716. /// the same as the name of the enclosing type node, but it can be different in e.g.
  7717. /// extensions in Extensible Sing#
  7718. /// </summary>
  7719. public virtual Identifier ConstructorName {
  7720. get {
  7721. if (this.constructorName == null) {
  7722. Identifier id = this.Name;
  7723. if (this.IsNormalized && this.IsGeneric)
  7724. id = Identifier.For(this.GetUnmangledNameWithoutTypeParameters());
  7725. this.constructorName = id;
  7726. }
  7727. return this.constructorName;
  7728. }
  7729. }
  7730. private Identifier constructorName;
  7731. /// <summary>True if the type is an abstract class or an interface.</summary>
  7732. public virtual bool IsAbstract{
  7733. get{
  7734. return (this.Flags & TypeFlags.Abstract) != 0;
  7735. }
  7736. }
  7737. public override bool IsAssembly{
  7738. get{
  7739. TypeFlags visibility = this.Flags & TypeFlags.VisibilityMask;
  7740. return visibility == TypeFlags.NotPublic || visibility == TypeFlags.NestedAssembly;
  7741. }
  7742. }
  7743. public override bool IsCompilerControlled{
  7744. get{return false;}
  7745. }
  7746. public override bool IsFamily{
  7747. get{return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedFamily;}
  7748. }
  7749. public override bool IsFamilyAndAssembly{
  7750. get{return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedFamANDAssem;}
  7751. }
  7752. public override bool IsFamilyOrAssembly{
  7753. get{return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedFamORAssem;}
  7754. }
  7755. protected bool isGeneric;
  7756. /// <summary>True if this type is a template conforming to the rules of a generic type in the CLR.</summary>
  7757. public virtual bool IsGeneric{
  7758. get{
  7759. return this.isGeneric;
  7760. }
  7761. set{
  7762. this.isGeneric = value;
  7763. }
  7764. }
  7765. #if ExtendedRuntime
  7766. public static bool IsImmutable(TypeNode type) {
  7767. type = TypeNode.StripModifiers(type);
  7768. if (type == null) return false;
  7769. if (type.TypeCode != TypeCode.Object) return true;
  7770. if (type.GetAttribute(SystemTypes.ImmutableAttribute) != null) return true;
  7771. if (type.IsValueType && type.DeclaringModule == CoreSystemTypes.SystemAssembly) return true; //hack.
  7772. return false;
  7773. }
  7774. #endif
  7775. public virtual bool IsNestedAssembly {
  7776. get{return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedAssembly;}
  7777. }
  7778. public virtual bool IsNestedFamily{
  7779. get{return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedFamily;}
  7780. }
  7781. public virtual bool IsNestedFamilyAndAssembly{
  7782. get{return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedFamANDAssem;}
  7783. }
  7784. public virtual bool IsNestedInternal{
  7785. get{return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedFamORAssem;}
  7786. }
  7787. public virtual bool IsNestedIn(TypeNode type){
  7788. for (TypeNode decType = this.DeclaringType; decType != null; decType = decType.DeclaringType){
  7789. if (decType == type) return true;
  7790. }
  7791. return false;
  7792. }
  7793. public virtual bool IsNestedPublic{
  7794. get{return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedPublic;}
  7795. }
  7796. public virtual bool IsNonPublic{
  7797. get{return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NotPublic;}
  7798. }
  7799. #if !MinimalReader
  7800. protected bool isNormalized;
  7801. /// <summary>
  7802. /// True if the type node is in "normal" form. A node is in "normal" form if it is effectively a node in an AST formed directly
  7803. /// from CLR module or assembly. Such a node can be written out as compiled code to an assembly or module without further processing.
  7804. /// </summary>
  7805. public virtual bool IsNormalized{
  7806. get{
  7807. if (this.isNormalized) return true;
  7808. if (this.DeclaringModule == null) return false;
  7809. return this.isNormalized = this.DeclaringModule.IsNormalized;
  7810. }
  7811. set{
  7812. this.isNormalized = value;
  7813. }
  7814. }
  7815. #endif
  7816. public override bool IsPrivate{
  7817. get{return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedPrivate;}
  7818. }
  7819. /// <summary>True if values of this type can be compared directly in CLR IL instructions.</summary>
  7820. public virtual bool IsPrimitiveComparable{
  7821. get{
  7822. switch(this.typeCode){
  7823. case ElementType.Boolean:
  7824. case ElementType.Char:
  7825. case ElementType.Int8:
  7826. case ElementType.Int16:
  7827. case ElementType.Int32:
  7828. case ElementType.Int64:
  7829. case ElementType.IntPtr:
  7830. case ElementType.UInt8:
  7831. case ElementType.UInt16:
  7832. case ElementType.UInt32:
  7833. case ElementType.UInt64:
  7834. case ElementType.UIntPtr:
  7835. case ElementType.Single:
  7836. case ElementType.Double:
  7837. return true;
  7838. default:
  7839. return !(this is Struct) || this is EnumNode || this is Pointer;
  7840. }
  7841. }
  7842. }
  7843. /// <summary>True if values of this type are integers that can be processed by CLR IL instructions.</summary>
  7844. public virtual bool IsPrimitiveInteger{
  7845. get{
  7846. switch(this.typeCode){
  7847. case ElementType.Int8:
  7848. case ElementType.Int16:
  7849. case ElementType.Int32:
  7850. case ElementType.Int64:
  7851. case ElementType.IntPtr:
  7852. case ElementType.UInt8:
  7853. case ElementType.UInt16:
  7854. case ElementType.UInt32:
  7855. case ElementType.UInt64:
  7856. case ElementType.UIntPtr:
  7857. return true;
  7858. default:
  7859. return false;
  7860. }
  7861. }
  7862. }
  7863. /// <summary>True if values of this type are integers or floating point numbers that can be processed by CLR IL instructions.</summary>
  7864. public virtual bool IsPrimitiveNumeric{
  7865. get{
  7866. switch(this.typeCode){
  7867. case ElementType.Int8:
  7868. case ElementType.Int16:
  7869. case ElementType.Int32:
  7870. case ElementType.Int64:
  7871. case ElementType.IntPtr:
  7872. case ElementType.UInt8:
  7873. case ElementType.UInt16:
  7874. case ElementType.UInt32:
  7875. case ElementType.UInt64:
  7876. case ElementType.UIntPtr:
  7877. case ElementType.Single:
  7878. case ElementType.Double:
  7879. return true;
  7880. default:
  7881. return false;
  7882. }
  7883. }
  7884. }
  7885. /// <summary>True if values of this type are unsigned integers that can be processed by CLR IL instructions.</summary>
  7886. public virtual bool IsPrimitiveUnsignedInteger {
  7887. get {
  7888. switch (this.typeCode) {
  7889. case ElementType.UInt8:
  7890. case ElementType.UInt16:
  7891. case ElementType.UInt32:
  7892. case ElementType.UInt64:
  7893. case ElementType.UIntPtr:
  7894. return true;
  7895. default:
  7896. return false;
  7897. }
  7898. }
  7899. }
  7900. public override bool IsPublic {
  7901. get{
  7902. TypeFlags visibility = this.Flags & TypeFlags.VisibilityMask;
  7903. return visibility == TypeFlags.Public || visibility == TypeFlags.NestedPublic;
  7904. }
  7905. }
  7906. /// <summary>True if values of this type can be processed by CLR IL instructions.</summary>
  7907. public virtual bool IsPrimitive{
  7908. get{
  7909. switch(this.typeCode){
  7910. case ElementType.Boolean:
  7911. case ElementType.Char:
  7912. case ElementType.Double:
  7913. case ElementType.Int16:
  7914. case ElementType.Int32:
  7915. case ElementType.Int64:
  7916. case ElementType.Int8:
  7917. case ElementType.IntPtr:
  7918. case ElementType.Single:
  7919. case ElementType.String:
  7920. case ElementType.UInt16:
  7921. case ElementType.UInt32:
  7922. case ElementType.UInt64:
  7923. case ElementType.UInt8:
  7924. case ElementType.UIntPtr:
  7925. return true;
  7926. default:
  7927. return false;
  7928. }
  7929. }
  7930. }
  7931. /// <summary>True if the type cannot be derived from.</summary>
  7932. public virtual bool IsSealed{
  7933. get{
  7934. return (this.Flags & TypeFlags.Sealed) != 0;
  7935. }
  7936. }
  7937. public override bool IsSpecialName{
  7938. get{return (this.Flags & TypeFlags.SpecialName) != 0;}
  7939. }
  7940. public override bool IsStatic{
  7941. get{return true;}
  7942. }
  7943. /// <summary>True if the identity of the type depends on its structure rather than its name.
  7944. /// Arrays, pointers and generic type instances are examples of such types.</summary>
  7945. public virtual bool IsStructural{
  7946. get{
  7947. return this.Template != null;
  7948. }
  7949. }
  7950. /// <summary>True if the type serves as a parameter to a type template.</summary>
  7951. public virtual bool IsTemplateParameter{
  7952. get{
  7953. return false;
  7954. }
  7955. }
  7956. /// <summary>True if the type is a value type containing only fields of unmanaged types.</summary>
  7957. public virtual bool IsUnmanaged{
  7958. get{
  7959. #if ExtendedRuntime
  7960. return IsPointerFree;
  7961. #else
  7962. return false;
  7963. #endif
  7964. }
  7965. }
  7966. /// <summary>A list of the types that contribute to the structure of a structural type.</summary>
  7967. public virtual TypeNodeList StructuralElementTypes{
  7968. get{
  7969. TypeNodeList result = this.TemplateArguments;
  7970. if (result != null && result.Count > 0) return result;
  7971. return this.TemplateParameters;
  7972. }
  7973. }
  7974. /// <summary>True if values of this type are unsigned integers that can be processed by CLR IL instructions.</summary>
  7975. public virtual bool IsUnsignedPrimitiveNumeric{
  7976. get{
  7977. switch(this.typeCode){
  7978. case ElementType.UInt8:
  7979. case ElementType.UInt16:
  7980. case ElementType.UInt32:
  7981. case ElementType.UInt64:
  7982. case ElementType.UIntPtr:
  7983. return true;
  7984. default:
  7985. return false;
  7986. }
  7987. }
  7988. }
  7989. /// <summary>True if instances of this type have no identity other than their value and are copied upon assignment.</summary>
  7990. public virtual bool IsValueType{
  7991. get{
  7992. switch(this.NodeType){
  7993. case NodeType.EnumNode:
  7994. #if !MinimalReader
  7995. case NodeType.ConstrainedType:
  7996. case NodeType.TupleType:
  7997. case NodeType.TypeAlias:
  7998. case NodeType.TypeIntersection:
  7999. case NodeType.TypeUnion: return true;
  8000. #endif
  8001. case NodeType.Struct: return true;
  8002. default: return false;
  8003. }
  8004. }
  8005. }
  8006. #if ExtendedRuntime
  8007. /// <summary>True if the type is a value type containing no managed or unmanaged pointers.</summary>
  8008. public virtual bool IsPointerFree
  8009. {
  8010. get
  8011. {
  8012. return false;
  8013. }
  8014. }
  8015. /// <summary>
  8016. /// Returns true if the type is definitely a reference type.
  8017. /// </summary>
  8018. public virtual bool IsReferenceType {
  8019. get {
  8020. switch (this.NodeType) {
  8021. case NodeType.Class:
  8022. case NodeType.Interface:
  8023. case NodeType.Pointer:
  8024. case NodeType.ArrayType:
  8025. case NodeType.DelegateNode:
  8026. return this != SystemTypes.ValueType && this != SystemTypes.Enum;
  8027. default:
  8028. return false;
  8029. }
  8030. }
  8031. }
  8032. #endif
  8033. /// <summary>
  8034. /// True if underlying type (modulo type modifiers) is a pointer type (Pointer)
  8035. /// </summary>
  8036. public virtual bool IsPointerType{
  8037. get { return false; }
  8038. }
  8039. public override bool IsVisibleOutsideAssembly{
  8040. get{
  8041. if (this.DeclaringType != null && !this.DeclaringType.IsVisibleOutsideAssembly) return false;
  8042. switch(this.Flags & TypeFlags.VisibilityMask){
  8043. case TypeFlags.Public:
  8044. case TypeFlags.NestedPublic:
  8045. return true;
  8046. case TypeFlags.NestedFamily:
  8047. case TypeFlags.NestedFamORAssem:
  8048. return this.DeclaringType != null && !this.DeclaringType.IsSealed;
  8049. default:
  8050. return false;
  8051. }
  8052. }
  8053. }
  8054. // This field stores those members declared syntactically within
  8055. // this type node. (Under Extended Sing#, additional members can
  8056. // be logically part of a type node but declared in a separate
  8057. // syntactic type node.)
  8058. protected internal MemberList members;
  8059. protected volatile internal bool membersBeingPopulated;
  8060. /// <summary>
  8061. /// The list of members contained inside this type, by default ignoring any extensions of this type.
  8062. /// (Subclasses in the Extensible Sing# dialect override this to include members of visible extensions.)
  8063. /// If the value of members is null and the value of ProvideTypeMembers is not null, the
  8064. /// TypeMemberProvider delegate is called to fill in the value of this property.
  8065. /// </summary>
  8066. public virtual MemberList Members{
  8067. get{
  8068. if (this.members == null || this.membersBeingPopulated)
  8069. if (this.ProvideTypeMembers != null && this.ProviderHandle != null){
  8070. lock (Module.GlobalLock){
  8071. if (this.members == null){
  8072. this.membersBeingPopulated = true;
  8073. this.ProvideTypeMembers(this, this.ProviderHandle);
  8074. this.membersBeingPopulated = false;
  8075. #if ExtendedRuntime
  8076. this.ApplyOutOfBandContracts();
  8077. #endif
  8078. }
  8079. }
  8080. }else
  8081. this.members = new MemberList();
  8082. return this.members;
  8083. }
  8084. set{
  8085. this.members = value;
  8086. this.memberCount = 0;
  8087. this.memberTable = null;
  8088. this.constructors = null;
  8089. this.defaultMembers = null;
  8090. #if !MinimalReader
  8091. this.explicitCoercionFromTable = null;
  8092. this.explicitCoercionMethods = null;
  8093. this.explicitCoercionToTable = null;
  8094. this.implicitCoercionFromTable = null;
  8095. this.implicitCoercionMethods = null;
  8096. this.implicitCoercionToTable = null;
  8097. this.opFalse = null;
  8098. this.opTrue = null;
  8099. #endif
  8100. }
  8101. }
  8102. #if ExtendedRuntime
  8103. protected internal TypeNode ContractType
  8104. {
  8105. get
  8106. {
  8107. AssemblyNode declaringAssembly = this.DeclaringModule as AssemblyNode;
  8108. if (declaringAssembly == null || declaringAssembly.ContractAssembly == null) return null;
  8109. if (this.DeclaringType == null)
  8110. {
  8111. return declaringAssembly.ContractAssembly.GetType(this.Namespace, this.Name);
  8112. }
  8113. else
  8114. {
  8115. TypeNode parentContractType = this.DeclaringType.ContractType;
  8116. if (parentContractType == null) return null;
  8117. return parentContractType.GetNestedType(this.Name);
  8118. }
  8119. }
  8120. }
  8121. protected internal virtual void ApplyOutOfBandContracts(){
  8122. if (this.members == null) return;
  8123. TypeNode contractType = this.ContractType;
  8124. if (contractType == null) return;
  8125. // Copy the type-level contract attributes over to the shadowed type, namely "this".
  8126. int contractsNamespaceKey = SystemTypes.NonNullType.Namespace.UniqueIdKey;
  8127. foreach (AttributeNode attr in contractType.Attributes) {
  8128. if (attr.Type.Namespace != null && attr.Type.Namespace.UniqueIdKey == contractsNamespaceKey)
  8129. this.Attributes.Add(attr);
  8130. }
  8131. if (this.BaseType != null) { MemberList junk = this.BaseType.Members; if (junk != null) junk = null; }
  8132. Hashtable contractByFullName = new Hashtable();
  8133. MemberList contractMembers = contractType.Members;
  8134. for (int i = 0, n = contractMembers == null ? 0 : contractMembers.Count; i < n; i++){
  8135. //^ assert contractMembers != null;
  8136. Field f = contractMembers[i] as Field;
  8137. if (f != null) {
  8138. contractByFullName[f.FullName] = f;
  8139. continue;
  8140. }
  8141. Method m = contractMembers[i] as Method;
  8142. if (m == null ) continue;
  8143. string methName = this.FullStrippedName(m);
  8144. contractByFullName[methName] = m;
  8145. }
  8146. for (int i = 0, n = members.Count; i < n; i++){
  8147. Field codeField = members[i] as Field;
  8148. if (codeField != null) {
  8149. Field contractField = contractByFullName[codeField.FullName] as Field;
  8150. if (contractField != null && contractField.Type != null && contractField.Type != codeField.Type) {
  8151. OptionalModifier optFieldType = contractField.Type as OptionalModifier;
  8152. if (optFieldType != null && codeField.Type != null) {
  8153. codeField.Type = OptionalModifier.For(optFieldType.Modifier, codeField.Type);
  8154. codeField.HasOutOfBandContract = true;
  8155. }
  8156. }
  8157. continue;
  8158. }
  8159. Method codeMethod = members[i] as Method;
  8160. if (codeMethod == null) continue;
  8161. // we include the return type since some conversion operators result
  8162. // in overloaded methods whose signatures differ only in return type
  8163. string methName = this.FullStrippedName(codeMethod);
  8164. Method contractMethod = contractByFullName[methName] as Method;
  8165. if (contractMethod != null) {
  8166. this.CopyContractToMethod(contractMethod, codeMethod);
  8167. if (codeMethod.OverridesBaseClassMember) {
  8168. Method overridden = this.FindNearestOverriddenMethod(contractMethod);
  8169. if (overridden != null)
  8170. this.CopyContractToMethod(overridden, codeMethod);
  8171. }
  8172. } else {
  8173. // Maybe there isn't a shadow method declared in contractType, but
  8174. // there still might be out-of-band contracts on an interface method
  8175. // that the codeMethod implements.
  8176. if (codeMethod.ImplementedInterfaceMethods != null && codeMethod.ImplementedInterfaceMethods.Count > 0) {
  8177. foreach (Method m in codeMethod.ImplementedInterfaceMethods) {
  8178. this.CopyContractToMethod(m, codeMethod);
  8179. }
  8180. } else if (codeMethod.ImplicitlyImplementedInterfaceMethods != null) {
  8181. foreach (Method m in codeMethod.ImplicitlyImplementedInterfaceMethods) {
  8182. this.CopyContractToMethod(m, codeMethod);
  8183. }
  8184. }
  8185. }
  8186. }
  8187. }
  8188. protected virtual string/*!*/ FullStrippedName(Method/*!*/ m) {
  8189. StringBuilder sb = new StringBuilder();
  8190. sb.Append(m.DeclaringType.GetFullUnmangledNameWithTypeParameters());
  8191. sb.Append('.');
  8192. if (m.NodeType == NodeType.InstanceInitializer)
  8193. sb.Append("#ctor");
  8194. else if (m.Name != null)
  8195. sb.Append(m.Name.ToString());
  8196. ParameterList parameters = m.Parameters;
  8197. for (int i = 0, n = parameters == null ? 0 : parameters.Count; i < n; i++){
  8198. Parameter par = parameters[i];
  8199. if (par == null || par.Type == null) continue;
  8200. TypeNode parType = TypeNode.DeepStripModifiers(par.Type);
  8201. Reference rt = parType as Reference;
  8202. if (rt != null && rt.ElementType != null)
  8203. parType = TypeNode.DeepStripModifiers(rt.ElementType).GetReferenceType();
  8204. //^ assert parType != null;
  8205. if (i == 0)
  8206. sb.Append('(');
  8207. else
  8208. sb.Append(',');
  8209. sb.Append(parType.GetFullUnmangledNameWithTypeParameters());
  8210. if (i == n-1)
  8211. sb.Append(')');
  8212. }
  8213. if (m.ReturnType != null){
  8214. TypeNode retType = TypeNode.DeepStripModifiers(m.ReturnType);
  8215. //^ assert retType != null;
  8216. sb.Append(retType.GetFullUnmangledNameWithTypeParameters());
  8217. }
  8218. return sb.ToString();
  8219. }
  8220. protected virtual void CopyContractToMethod(Method/*!*/ contractMethod, Method/*!*/ codeMethod) {
  8221. codeMethod.HasOutOfBandContract = true;
  8222. if (codeMethod.Contract == null)
  8223. codeMethod.Contract = new MethodContract(codeMethod);
  8224. // setting them to null forces deserialization upon next access to the property
  8225. // NB: This means that out-of-band contracts can be applied *only* to code that
  8226. // does *not* have any contracts since this will wipe them out!!
  8227. codeMethod.Contract.Ensures = null;
  8228. codeMethod.Contract.Modifies = null;
  8229. codeMethod.Contract.Requires = null;
  8230. int contractsNamespaceKey = SystemTypes.NonNullType.Namespace.UniqueIdKey;
  8231. // Copy the method-level contract attributes over to the shadowed method.
  8232. for (int a = 0; a < contractMethod.Attributes.Count; a++){
  8233. AttributeNode attr = contractMethod.Attributes[a];
  8234. if (attr != null && attr.Type != null && attr.Type.Namespace != null &&
  8235. attr.Type.Namespace != null && attr.Type.Namespace.UniqueIdKey == contractsNamespaceKey)
  8236. codeMethod.Attributes.Add(attr);
  8237. }
  8238. // Copy over any return attributes to the shadowed method
  8239. for (int a = 0, n = contractMethod.ReturnAttributes == null ? 0 : contractMethod.ReturnAttributes.Count; a < n; a++) {
  8240. AttributeNode attr = contractMethod.ReturnAttributes[a];
  8241. if (attr != null) {
  8242. if (attr.Type.Namespace != null && attr.Type.Namespace.UniqueIdKey == contractsNamespaceKey) {
  8243. if (codeMethod.ReturnAttributes == null) {
  8244. codeMethod.ReturnAttributes = new AttributeList();
  8245. }
  8246. codeMethod.ReturnAttributes.Add(attr);
  8247. }
  8248. }
  8249. }
  8250. // Copy the parameter-level contract attributes and type over to the shadowed method's parameters.
  8251. ParameterList contractParameters = contractMethod.Parameters;
  8252. ParameterList codeParameters = codeMethod.Parameters;
  8253. if (contractParameters != null && codeParameters != null && contractParameters.Count <= codeParameters.Count) {
  8254. for (int i = 0, n = contractParameters.Count; i < n; i++) {
  8255. Parameter contractParameter = contractParameters[i];
  8256. Parameter codeParameter = codeParameters[i];
  8257. if (contractParameter == null || codeParameter == null) continue;
  8258. for (int a = 0, m = contractParameter.Attributes == null ? 0 : contractParameter.Attributes.Count; a < m; a++){
  8259. //^ assert contractParameter.Attributes != null;
  8260. AttributeNode attr = contractParameter.Attributes[a];
  8261. if (attr == null || attr.Type == null) continue;
  8262. if (attr.Type.Namespace != null && attr.Type.Namespace.UniqueIdKey == contractsNamespaceKey){
  8263. if (codeParameter.Attributes == null) codeParameter.Attributes = new AttributeList();
  8264. codeParameter.Attributes.Add(attr);
  8265. }
  8266. }
  8267. if (contractParameter.Type != codeParameter.Type)
  8268. codeParameter.Type = this.CopyModifier(contractParameter.Type, codeParameter.Type);
  8269. }
  8270. }
  8271. if (contractMethod.ReturnType != codeMethod.ReturnType)
  8272. codeMethod.ReturnType = this.CopyModifier(contractMethod.ReturnType, codeMethod.ReturnType);
  8273. codeMethod.fullName = null;
  8274. }
  8275. private TypeNode CopyModifier(TypeNode contractType, TypeNode codeType) {
  8276. if (contractType == null) return codeType;
  8277. Reference rcType = contractType as Reference;
  8278. if (rcType != null) {
  8279. contractType = rcType.ElementType;
  8280. if (contractType == null) return codeType;
  8281. Reference rcodeType = codeType as Reference;
  8282. if (rcodeType == null || rcodeType.ElementType == null) return codeType;
  8283. TypeNode t = CopyModifier(contractType, rcodeType.ElementType);
  8284. return t.GetReferenceType();
  8285. }
  8286. ArrayType acType = contractType as ArrayType;
  8287. if (acType != null) {
  8288. contractType = acType.ElementType;
  8289. if (contractType == null) return codeType;
  8290. ArrayType acodeType = codeType as ArrayType;
  8291. if (acodeType == null || acodeType.ElementType == null) return codeType;
  8292. TypeNode t = CopyModifier(contractType, acodeType.ElementType);
  8293. return t.GetArrayType(1);
  8294. }
  8295. OptionalModifier optModType = contractType as OptionalModifier;
  8296. if (optModType != null && optModType.Modifier != null) {
  8297. TypeNode t = CopyModifier(optModType.ModifiedType, codeType);
  8298. codeType = OptionalModifier.For(optModType.Modifier, t);
  8299. }
  8300. if (contractType.Template != null && codeType.Template != null && contractType.TemplateArguments != null && codeType.TemplateArguments != null) {
  8301. TypeNodeList args = contractType.TemplateArguments.Clone();
  8302. TypeNodeList codeArgs = codeType.TemplateArguments;
  8303. for (int i = 0, n = args.Count, m = codeArgs.Count; i < n && i < m; i++) {
  8304. TypeNode argType = args[i];
  8305. TypeNode codeArgType = codeArgs[i];
  8306. if (argType != codeArgType)
  8307. args[i] = this.CopyModifier(argType, codeArgType);
  8308. }
  8309. return codeType.Template.GetTemplateInstance(codeType, args);
  8310. }
  8311. return codeType;
  8312. }
  8313. public virtual Method FindNearestOverriddenMethod (Method method)
  8314. //^ requires method.IsVirtual;
  8315. {
  8316. if (method == null) return null;
  8317. if (!method.IsVirtual) return null;
  8318. int numParams = method.Parameters == null ? 0 : method.Parameters.Count;
  8319. TypeNode[] paramTypes = new TypeNode[numParams];
  8320. for (int i=0; i<numParams; i++) paramTypes[i] = method.Parameters[i].Type;
  8321. for (TypeNode scan = method.DeclaringType.BaseType; scan != null; scan = scan.BaseType){
  8322. Method overridden = scan.GetMethod(method.Name, paramTypes);
  8323. if (overridden != null) return overridden;
  8324. }
  8325. return null;
  8326. }
  8327. public TypeNodeList ReferencedTemplateInstances;
  8328. #endif
  8329. protected TypeNode template;
  8330. /// <summary>The (generic) type template from which this type was instantiated. Null if this is not a (generic) type template instance.</summary>
  8331. public virtual TypeNode Template{
  8332. get{
  8333. TypeNode result = this.template;
  8334. if (result == null){
  8335. if (this.isGeneric || TargetPlatform.GenericTypeNamesMangleChar != '_') return null;
  8336. AttributeList attributes = this.Attributes;
  8337. lock(this){
  8338. if (this.template != null){
  8339. if (this.template == TypeNode.NotSpecified)
  8340. return null;
  8341. return this.template;
  8342. }
  8343. #if ExtendedRuntime
  8344. for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++) {
  8345. AttributeNode attr = attributes[i];
  8346. if (attr == null) continue;
  8347. MemberBinding mb = attr.Constructor as MemberBinding;
  8348. if (mb == null || mb.BoundMember == null || mb.BoundMember.DeclaringType != SystemTypes.TemplateInstanceAttribute) continue;
  8349. ExpressionList exprs = attr.Expressions;
  8350. if (exprs == null || exprs.Count != 2) continue;
  8351. Literal lit = exprs[0] as Literal;
  8352. if (lit == null) continue;
  8353. TypeNode templ = lit.Value as TypeNode;
  8354. if (templ != null) {
  8355. lit = exprs[1] as Literal;
  8356. if (lit == null) continue;
  8357. object[] types = lit.Value as object[];
  8358. if (types == null) continue;
  8359. int m = types == null ? 0 : types.Length;
  8360. TypeNodeList templateArguments = new TypeNodeList(m);
  8361. for (int j = 0; j < m; j++) {
  8362. TypeNode t = types[j] as TypeNode;
  8363. if (t == null) continue;
  8364. templateArguments.Add(t);
  8365. }
  8366. this.TemplateArguments = templateArguments;
  8367. return this.template = templ;
  8368. }
  8369. }
  8370. #endif
  8371. if (result == null)
  8372. this.template = TypeNode.NotSpecified;
  8373. }
  8374. }else if (result == TypeNode.NotSpecified)
  8375. return null;
  8376. return result;
  8377. }
  8378. set{
  8379. this.template = value;
  8380. }
  8381. }
  8382. #if !MinimalReader
  8383. public TypeNode TemplateExpression;
  8384. #endif
  8385. protected TypeNodeList templateArguments;
  8386. /// <summary>The arguments used when this (generic) type template instance was instantiated.</summary>
  8387. public virtual TypeNodeList TemplateArguments{
  8388. get{
  8389. if (this.template == null){
  8390. TypeNode templ = this.Template; //Will fill in the arguments
  8391. if (templ != null) templ = null;
  8392. }
  8393. return this.templateArguments;
  8394. }
  8395. set{
  8396. this.templateArguments = value;
  8397. }
  8398. }
  8399. #if !MinimalReader
  8400. public TypeNodeList TemplateArgumentExpressions;
  8401. #endif
  8402. internal TypeNodeList consolidatedTemplateArguments;
  8403. public virtual TypeNodeList ConsolidatedTemplateArguments{
  8404. get{
  8405. if (this.consolidatedTemplateArguments == null)
  8406. this.consolidatedTemplateArguments = this.GetConsolidatedTemplateArguments();
  8407. return this.consolidatedTemplateArguments;
  8408. }
  8409. set{
  8410. this.consolidatedTemplateArguments = value;
  8411. }
  8412. }
  8413. private void AddTemplateParametersFromAttributeEncoding(TypeNodeList result)
  8414. {
  8415. #if ExtendedRuntime
  8416. if (result.Count == 0) {
  8417. AttributeList attributes = this.Attributes;
  8418. for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++) {
  8419. AttributeNode attr = attributes[i];
  8420. if (attr == null) continue;
  8421. MemberBinding mb = attr.Constructor as MemberBinding;
  8422. if (mb == null || mb.BoundMember == null || mb.BoundMember.DeclaringType != SystemTypes.TemplateAttribute) continue;
  8423. ExpressionList exprs = attr.Expressions;
  8424. if (exprs == null || exprs.Count != 1) continue;
  8425. Literal lit = exprs[0] as Literal;
  8426. if (lit == null) continue;
  8427. object[] types = lit.Value as object[];
  8428. if (types == null) continue;
  8429. for (int j = 0, m = types == null ? 0 : types.Length; j < m; j++) {
  8430. TypeNode t = types[j] as TypeNode;
  8431. if (t == null) continue;
  8432. if (t.NodeType == NodeType.TypeParameter || t.NodeType == NodeType.ClassParameter)
  8433. result.Add(t);
  8434. }
  8435. attributes[i] = null;
  8436. }
  8437. }
  8438. #endif
  8439. }
  8440. internal TypeNodeList templateParameters;
  8441. /// <summary>The type parameters of this type. Null if this type is not a (generic) type template.</summary>
  8442. public virtual TypeNodeList TemplateParameters{
  8443. get{
  8444. TypeNodeList result = this.templateParameters;
  8445. if (result == null){
  8446. if (this.isGeneric || TargetPlatform.GenericTypeNamesMangleChar != '_') return null; //Can happen when this is nested in a generic type
  8447. TypeNodeList nestedTypes = this.NestedTypes;
  8448. lock (this) {
  8449. if ((result = this.templateParameters) != null) return result.Count == 0 ? null : result;
  8450. result = new TypeNodeList();
  8451. for (int i = 0, n = nestedTypes == null ? 0 : nestedTypes.Count; i < n; i++) {
  8452. TypeNode nt = nestedTypes[i];
  8453. if (nt == null) continue;
  8454. if (nt is MethodTypeParameter) continue;
  8455. if (nt.NodeType == NodeType.TypeParameter || nt.NodeType == NodeType.ClassParameter)
  8456. result.Add(nt);
  8457. }
  8458. this.AddTemplateParametersFromAttributeEncoding(result);
  8459. this.TemplateParameters = result;
  8460. }
  8461. }
  8462. if (result.Count == 0) return null;
  8463. return result;
  8464. }
  8465. set{
  8466. if (value == null){
  8467. if (this.templateParameters == null) return;
  8468. if (this.templateParameters.Count > 0)
  8469. value = new TypeNodeList(0);
  8470. }
  8471. this.templateParameters = value;
  8472. }
  8473. }
  8474. protected internal TypeNodeList consolidatedTemplateParameters;
  8475. public virtual TypeNodeList ConsolidatedTemplateParameters{
  8476. get{
  8477. if (this.consolidatedTemplateParameters == null)
  8478. this.consolidatedTemplateParameters = this.GetConsolidatedTemplateParameters();
  8479. return this.consolidatedTemplateParameters;
  8480. }
  8481. set{
  8482. this.consolidatedTemplateParameters = value;
  8483. }
  8484. }
  8485. internal ElementType typeCode = ElementType.Class;
  8486. /// <summary>The System.TypeCode value that Convert.GetTypeCode will return pass an instance of this type as parameter.</summary>
  8487. public virtual System.TypeCode TypeCode{
  8488. get{
  8489. switch(this.typeCode){
  8490. case ElementType.Boolean : return System.TypeCode.Boolean;
  8491. case ElementType.Char : return System.TypeCode.Char;
  8492. case ElementType.Double : return System.TypeCode.Double;
  8493. case ElementType.Int16 : return System.TypeCode.Int16;
  8494. case ElementType.Int32 : return System.TypeCode.Int32;
  8495. case ElementType.Int64 : return System.TypeCode.Int64;
  8496. case ElementType.Int8 : return System.TypeCode.SByte;
  8497. case ElementType.Single : return System.TypeCode.Single;
  8498. case ElementType.UInt16 : return System.TypeCode.UInt16;
  8499. case ElementType.UInt32 : return System.TypeCode.UInt32;
  8500. case ElementType.UInt64 : return System.TypeCode.UInt64;
  8501. case ElementType.UInt8 : return System.TypeCode.Byte;
  8502. case ElementType.Void : return System.TypeCode.Empty;
  8503. default:
  8504. if (this == CoreSystemTypes.String) return System.TypeCode.String;
  8505. #if !MinimalReader
  8506. if (this == CoreSystemTypes.Decimal) return System.TypeCode.Decimal;
  8507. if (this == CoreSystemTypes.DateTime) return System.TypeCode.DateTime;
  8508. if (this == CoreSystemTypes.DBNull) return System.TypeCode.DBNull;
  8509. #endif
  8510. return System.TypeCode.Object;
  8511. }
  8512. }
  8513. }
  8514. private readonly static TypeNode NotSpecified = new Class();
  8515. #if !FxCop
  8516. protected
  8517. #endif
  8518. internal TrivialHashtableUsingWeakReferences structurallyEquivalentMethod;
  8519. #if !MinimalReader
  8520. /// <summary>
  8521. /// Returns the methods of an abstract type that have been left unimplemented. Includes methods inherited from
  8522. /// base classes and interfaces, and methods from any (known) extensions.
  8523. /// </summary>
  8524. /// <param name="result">A method list to which the abstract methods must be appended.</param>
  8525. public virtual void GetAbstractMethods(MethodList/*!*/ result) {
  8526. if (!this.IsAbstract) return;
  8527. //For each interface, get abstract methods and keep those that are not implemented by this class or a base class
  8528. InterfaceList interfaces = this.Interfaces;
  8529. for (int i = 0, n = interfaces == null ? 0 : interfaces.Count; i < n; i++){
  8530. Interface iface = interfaces[i];
  8531. if (iface == null) continue;
  8532. MemberList imembers = iface.Members;
  8533. for (int j = 0, m = imembers == null ? 0 : imembers.Count; j < m; j++){
  8534. Method meth = imembers[j] as Method;
  8535. if (meth == null) continue;
  8536. if (this.ImplementsExplicitly(meth)) continue;
  8537. if (this.ImplementsMethod(meth, true)) continue;
  8538. result.Add(meth);
  8539. }
  8540. }
  8541. }
  8542. #endif
  8543. protected internal TrivialHashtable szArrayTypes;
  8544. /// <summary>
  8545. /// Returns a type representing an array whose elements are of this type. Will always return the same instance for the same rank.
  8546. /// </summary>
  8547. /// <param name="rank">The number of dimensions of the array.</param>
  8548. public virtual ArrayType/*!*/ GetArrayType(int rank) {
  8549. return this.GetArrayType(rank, false);
  8550. }
  8551. public virtual ArrayType/*!*/ GetArrayType(int rank, bool lowerBoundIsUnknown) {
  8552. if (rank > 1 || lowerBoundIsUnknown) return this.GetArrayType(rank, 0, 0, new int[0], new int[0]);
  8553. if (this.szArrayTypes == null) this.szArrayTypes = new TrivialHashtable();
  8554. ArrayType result = (ArrayType)this.szArrayTypes[rank];
  8555. if (result != null) return result;
  8556. lock(this){
  8557. result = (ArrayType)this.szArrayTypes[rank];
  8558. if (result != null) return result;
  8559. this.szArrayTypes[rank] = result = new ArrayType(this, 1);
  8560. result.Flags &= ~TypeFlags.VisibilityMask;
  8561. result.Flags |= this.Flags & TypeFlags.VisibilityMask;
  8562. return result;
  8563. }
  8564. }
  8565. protected internal TrivialHashtable arrayTypes;
  8566. /// <summary>
  8567. /// Returns a type representing an array whose elements are of this type. Will always return the same instance for the same rank, sizes and bounds.
  8568. /// </summary>
  8569. /// <param name="rank">The number of dimensions of the array.</param>
  8570. /// <param name="sizes">The size of each dimension.</param>
  8571. /// <param name="loBounds">The lower bound for indices. Defaults to zero.</param>
  8572. public virtual ArrayType/*!*/ GetArrayType(int rank, int[] sizes, int[] loBounds) {
  8573. return this.GetArrayType(rank, sizes == null ? 0 : sizes.Length, loBounds == null ? 0 : loBounds.Length, sizes == null ? new int[0] : sizes, loBounds == null ? new int[0] : loBounds);
  8574. }
  8575. internal ArrayType/*!*/ GetArrayType(int rank, int numSizes, int numLoBounds, int[]/*!*/ sizes, int[]/*!*/ loBounds) {
  8576. if (this.arrayTypes == null) this.arrayTypes = new TrivialHashtable();
  8577. StringBuilder sb = new StringBuilder(rank*5);
  8578. for (int i = 0; i < rank; i++){
  8579. if (i < numLoBounds) sb.Append(loBounds[i]); else sb.Append('0');
  8580. if (i < numSizes){sb.Append(':'); sb.Append(sizes[i]);}
  8581. sb.Append(',');
  8582. }
  8583. Identifier id = Identifier.For(sb.ToString());
  8584. ArrayType result = (ArrayType)this.arrayTypes[id.UniqueIdKey];
  8585. if (result != null) return result;
  8586. lock(this){
  8587. result = (ArrayType)this.arrayTypes[id.UniqueIdKey];
  8588. if (result != null) return result;
  8589. if (loBounds == null) loBounds = new int[0];
  8590. this.arrayTypes[id.UniqueIdKey] = result = new ArrayType(this, rank, sizes, loBounds);
  8591. result.Flags &= ~TypeFlags.VisibilityMask;
  8592. result.Flags |= this.Flags & TypeFlags.VisibilityMask;
  8593. return result;
  8594. }
  8595. }
  8596. protected internal MemberList constructors;
  8597. public virtual MemberList GetConstructors(){
  8598. if (this.Members.Count != this.memberCount) this.constructors = null;
  8599. if (this.constructors != null) return this.constructors;
  8600. lock(this){
  8601. if (this.constructors != null) return this.constructors;
  8602. return this.constructors = TypeNode.WeedOutNonSpecialMethods(this.GetMembersNamed(StandardIds.Ctor), MethodFlags.RTSpecialName);
  8603. }
  8604. }
  8605. /// <summary>
  8606. /// Returns the constructor with the specified parameter types. Returns null if this type has no such constructor.
  8607. /// </summary>
  8608. public virtual InstanceInitializer GetConstructor(params TypeNode[] types){
  8609. return (InstanceInitializer)GetFirstMethod(this.GetConstructors(), types);
  8610. }
  8611. #if !NoXml
  8612. protected override Identifier GetDocumentationId(){
  8613. if (this.DeclaringType == null)
  8614. return Identifier.For("T:"+this.FullName);
  8615. else
  8616. return Identifier.For(this.DeclaringType.DocumentationId+"."+this.Name);
  8617. }
  8618. internal virtual void AppendDocumentIdMangledName(StringBuilder/*!*/ sb, TypeNodeList methodTypeParameters, TypeNodeList typeParameters) {
  8619. if (this.DeclaringType != null) {
  8620. this.DeclaringType.AppendDocumentIdMangledName(sb, methodTypeParameters, typeParameters);
  8621. sb.Append('.');
  8622. sb.Append(this.GetUnmangledNameWithoutTypeParameters());
  8623. }else
  8624. sb.Append(this.GetFullUnmangledNameWithoutTypeParameters());
  8625. TypeNodeList templateArguments = this.TemplateArguments;
  8626. int n = templateArguments == null ? 0 : templateArguments.Count;
  8627. if (n == 0) return;
  8628. sb.Append('{');
  8629. for (int i = 0; i < n; i++){
  8630. //^ assert templateArguments != null;
  8631. TypeNode templArg = templateArguments[i];
  8632. if (templArg == null) continue;
  8633. templArg.AppendDocumentIdMangledName(sb, methodTypeParameters, typeParameters);
  8634. if (i < n-1) sb.Append(',');
  8635. }
  8636. sb.Append('}');
  8637. }
  8638. #endif
  8639. internal TrivialHashtable modifierTable;
  8640. internal TypeNode/*!*/ GetModified(TypeNode/*!*/ modifierType, bool optionalModifier) {
  8641. if (this.modifierTable == null) this.modifierTable = new TrivialHashtable();
  8642. TypeNode result = (TypeNode)this.modifierTable[modifierType.UniqueKey];
  8643. if (result != null) return result;
  8644. result = optionalModifier ? (TypeNode)new OptionalModifier(modifierType, this) : (TypeNode)new RequiredModifier(modifierType, this);
  8645. this.modifierTable[modifierType.UniqueKey] = result;
  8646. return result;
  8647. }
  8648. public virtual TypeNode/*!*/ GetGenericTemplateInstance(Module/*!*/ module, TypeNodeList/*!*/ consolidatedArguments) {
  8649. if (this.DeclaringType == null)
  8650. return this.GetTemplateInstance(module, null, null, consolidatedArguments);
  8651. TypeNodeList myArgs = this.GetOwnTemplateArguments(consolidatedArguments);
  8652. if (myArgs == consolidatedArguments)
  8653. return this.GetTemplateInstance(module, null, this.DeclaringType, consolidatedArguments);
  8654. int n = consolidatedArguments.Count;
  8655. int m = myArgs == null ? 0 : myArgs.Count;
  8656. int k = n - m;
  8657. Debug.Assert(k > 0);
  8658. TypeNodeList parentArgs = new TypeNodeList(k);
  8659. for (int i = 0; i < k; i++) parentArgs.Add(consolidatedArguments[i]);
  8660. TypeNode declaringType = this.DeclaringType.GetGenericTemplateInstance(module, parentArgs);
  8661. TypeNode nestedType = declaringType.GetNestedType(this.Name);
  8662. if (nestedType == null) {
  8663. // can happen if a new nested type is added to a template
  8664. // see if the type appears in the original parent template
  8665. TypeNode declaringTypeTemplate = declaringType.Template;
  8666. TypeNode nestedTemplate = declaringTypeTemplate.GetNestedType(this.Name);
  8667. Duplicator duplicator = new Duplicator(module, null);
  8668. duplicator.RecordOriginalAsTemplate = true;
  8669. duplicator.SkipBodies = true;
  8670. duplicator.TypesToBeDuplicated[this.UniqueKey] = this;
  8671. nestedType = duplicator.VisitTypeNode(this, null, null, null, true);
  8672. Specializer specializer = new Specializer(module, declaringTypeTemplate.ConsolidatedTemplateParameters, declaringType.ConsolidatedTemplateArguments);
  8673. specializer.VisitTypeNode(nestedType);
  8674. nestedType.DeclaringType = declaringType;
  8675. declaringType.NestedTypes.Add(nestedType);
  8676. // Debug.Fail("template declaring type dummy instance does not have a nested type corresponding to template"); nestedType = this;
  8677. }
  8678. if (m == 0){Debug.Assert(nestedType.template != null); return nestedType;}
  8679. return nestedType.GetTemplateInstance(module, null, declaringType, myArgs);
  8680. }
  8681. public virtual TypeNode/*!*/ GetTemplateInstance(Module module, params TypeNode[] typeArguments) {
  8682. return this.GetTemplateInstance(module, null, null, new TypeNodeList(typeArguments));
  8683. }
  8684. protected virtual void TryToFindExistingInstance(Module/*!*/ module, TypeNode declaringType, TypeNodeList/*!*/ templateArguments, Identifier/*!*/ mangledName,
  8685. Identifier/*!*/ uniqueMangledName, out TypeNode result, out Identifier unusedMangledName){
  8686. unusedMangledName = null;
  8687. string mangledNameString = mangledName.Name;
  8688. int n = templateArguments.Count;
  8689. int tiCount = 0;
  8690. bool lookInReferencedAssemblies = TargetPlatform.GenericTypeNamesMangleChar != '`'; //REVIEW: huh? why not use IsGeneric?
  8691. result = module.GetStructurallyEquivalentType(this.Namespace == null ? Identifier.Empty : this.Namespace, mangledName, uniqueMangledName, lookInReferencedAssemblies);
  8692. if (this.IsGeneric){
  8693. if (result == null) unusedMangledName = mangledName;
  8694. return;
  8695. }
  8696. while (result != null){
  8697. //Mangled name is the same. But mangling is not unique (types are not qualified with assemblies), so check for equality.
  8698. if (this == result.Template && (declaringType == result.DeclaringType || !this.IsGeneric)){
  8699. bool goodMatch = (result.TemplateArguments != null || n == 0) && result.TemplateArguments.Count == n;
  8700. for (int i = 0; goodMatch && i < n; i++)
  8701. goodMatch = templateArguments[i] == result.TemplateArguments[i];
  8702. if (goodMatch) return;
  8703. }
  8704. //Mangle some more
  8705. mangledName = new Identifier(mangledNameString+(++tiCount).ToString());
  8706. result = module.GetStructurallyEquivalentType(this.Namespace == null ? Identifier.Empty : this.Namespace, mangledName, null, lookInReferencedAssemblies);
  8707. }
  8708. if (result == null) unusedMangledName = mangledName;
  8709. }
  8710. public virtual Identifier/*!*/ GetMangledTemplateInstanceName(TypeNodeList/*!*/ templateArguments, out Identifier/*!*/ uniqueMangledName, out bool notFullySpecialized){
  8711. StringBuilder mangledNameBuilder = new StringBuilder(this.Name.ToString());
  8712. StringBuilder uniqueMangledNameBuilder = new StringBuilder(this.Name.ToString());
  8713. uniqueMangledNameBuilder.Append(this.UniqueKey);
  8714. notFullySpecialized = false;
  8715. for (int i = 0, n = templateArguments.Count; i < n; i++){
  8716. if (i == 0){mangledNameBuilder.Append('<'); uniqueMangledNameBuilder.Append('<');}
  8717. TypeNode t = templateArguments[i];
  8718. if (t == null || t.Name == null) continue;
  8719. if (TypeIsNotFullySpecialized(t)) notFullySpecialized = true;
  8720. mangledNameBuilder.Append(t.FullName);
  8721. uniqueMangledNameBuilder.Append(t.FullName);
  8722. uniqueMangledNameBuilder.Append(t.UniqueKey);
  8723. if (i < n-1){
  8724. mangledNameBuilder.Append(',');
  8725. uniqueMangledNameBuilder.Append(',');
  8726. }else{
  8727. mangledNameBuilder.Append('>');
  8728. uniqueMangledNameBuilder.Append('>');
  8729. }
  8730. }
  8731. uniqueMangledName = Identifier.For(uniqueMangledNameBuilder.ToString());
  8732. return Identifier.For(mangledNameBuilder.ToString());
  8733. }
  8734. private static bool TypeIsNotFullySpecialized(TypeNode t) {
  8735. TypeNode tt = TypeNode.StripModifiers(t);
  8736. //^ assert tt != null;
  8737. if (tt is TypeParameter || tt is ClassParameter || tt.IsNotFullySpecialized)
  8738. return true;
  8739. for (int j = 0, m = tt.StructuralElementTypes == null ? 0 : tt.StructuralElementTypes.Count; j < m; j++) {
  8740. TypeNode et = tt.StructuralElementTypes[j];
  8741. if (et == null) continue;
  8742. if (TypeIsNotFullySpecialized(et)) return true;
  8743. }
  8744. return false;
  8745. }
  8746. /// <summary>
  8747. /// Gets an instance for the given template arguments of this (generic) template type.
  8748. /// </summary>
  8749. /// <param name="referringType">The type in which the reference to the template instance occurs. If the template is not
  8750. /// generic, the instance becomes a nested type of the referring type so that it has the same access privileges as the
  8751. /// code referrring to the instance.</param>
  8752. /// <param name="templateArguments">The template arguments.</param>
  8753. /// <returns>An instance of the template. Always the same instance for the same arguments.</returns>
  8754. public virtual TypeNode/*!*/ GetTemplateInstance(TypeNode referringType, params TypeNode[] templateArguments) {
  8755. return this.GetTemplateInstance(referringType, new TypeNodeList(templateArguments));
  8756. }
  8757. /// <summary>
  8758. /// Gets an instance for the given template arguments of this (generic) template type.
  8759. /// </summary>
  8760. /// <param name="referringType">The type in which the reference to the template instance occurs. If the template is not
  8761. /// generic, the instance becomes a nested type of the referring type so that it has the same access privileges as the
  8762. /// code referrring to the instance.</param>
  8763. /// <param name="templateArguments">The template arguments.</param>
  8764. /// <returns>An instance of the template. Always the same instance for the same arguments.</returns>
  8765. public virtual TypeNode/*!*/ GetTemplateInstance(TypeNode referringType, TypeNodeList templateArguments) {
  8766. if (referringType == null) return this;
  8767. Module module = referringType.DeclaringModule;
  8768. return this.GetTemplateInstance(module, referringType, this.DeclaringType, templateArguments);
  8769. }
  8770. class CachingModuleForGenericsInstances : Module{
  8771. public override TypeNode GetStructurallyEquivalentType(Identifier ns, Identifier/*!*/ id, Identifier uniqueMangledName, bool lookInReferencedAssemblies) {
  8772. if (uniqueMangledName == null) return null;
  8773. return (TypeNode)this.StructurallyEquivalentType[uniqueMangledName.UniqueIdKey];
  8774. }
  8775. }
  8776. protected static Module/*!*/ cachingModuleForGenericInstances = new CachingModuleForGenericsInstances();
  8777. public virtual TypeNode/*!*/ GetTemplateInstance(Module module, TypeNode referringType, TypeNode declaringType, TypeNodeList templateArguments) {
  8778. TypeNodeList templateParameters = this.TemplateParameters;
  8779. if (module == null || templateArguments == null || (declaringType == null && (templateParameters == null || templateParameters.Count == 0)))
  8780. return this;
  8781. if (this.IsGeneric){
  8782. referringType = null;
  8783. module = TypeNode.cachingModuleForGenericInstances;
  8784. }
  8785. bool notFullySpecialized;
  8786. Identifier/*!*/ uniqueMangledName;
  8787. Identifier mangledName = this.GetMangledTemplateInstanceName(templateArguments, out uniqueMangledName, out notFullySpecialized);
  8788. TypeNode result;
  8789. Identifier dummyId;
  8790. this.TryToFindExistingInstance(module, declaringType, templateArguments, mangledName, uniqueMangledName, out result, out dummyId);
  8791. if (result != null) return result;
  8792. if (this.NewTemplateInstanceIsRecursive) return this; //An instance of this template is trying to instantiate the template again
  8793. lock (Module.GlobalLock){
  8794. Identifier unusedMangledName;
  8795. this.TryToFindExistingInstance(module, declaringType, templateArguments, mangledName, uniqueMangledName, out result, out unusedMangledName);
  8796. if (result != null) return result;
  8797. //^ assume unusedMangledName != null;
  8798. TypeNodeList consolidatedTemplateArguments =
  8799. declaringType == null ? templateArguments : declaringType.GetConsolidatedTemplateArguments(templateArguments);
  8800. Duplicator duplicator = new Duplicator(module, referringType);
  8801. duplicator.RecordOriginalAsTemplate = true;
  8802. duplicator.SkipBodies = true;
  8803. duplicator.TypesToBeDuplicated[this.UniqueKey] = this;
  8804. result = duplicator.VisitTypeNode(this, unusedMangledName, consolidatedTemplateArguments, this.Template == null ? this : this.Template, true);
  8805. //^ assume result != null;
  8806. if (module == this.DeclaringModule){
  8807. if (this.TemplateInstances == null) this.TemplateInstances = new TypeNodeList();
  8808. this.TemplateInstances.Add(result);
  8809. }
  8810. result.Name = unusedMangledName;
  8811. result.Name.SourceContext = this.Name.SourceContext;
  8812. result.fullName = null;
  8813. if (this.IsGeneric) result.DeclaringModule = this.DeclaringModule;
  8814. result.DeclaringType = this.IsGeneric || referringType == null ? declaringType : referringType;
  8815. result.Template = this;
  8816. result.templateParameters = new TypeNodeList(0);
  8817. result.consolidatedTemplateParameters = new TypeNodeList(0);
  8818. result.templateArguments = templateArguments;
  8819. result.consolidatedTemplateArguments = consolidatedTemplateArguments;
  8820. result.IsNotFullySpecialized = notFullySpecialized || (declaringType != null && TypeIsNotFullySpecialized(declaringType));
  8821. module.StructurallyEquivalentType[unusedMangledName.UniqueIdKey] = result;
  8822. module.StructurallyEquivalentType[uniqueMangledName.UniqueIdKey] = result;
  8823. Specializer specializer = new Specializer(module, this.ConsolidatedTemplateParameters, consolidatedTemplateArguments);
  8824. specializer.VisitTypeNode(result);
  8825. TypeFlags visibility = this.Flags & TypeFlags.VisibilityMask;
  8826. for (int i = 0, m = templateArguments.Count; i < m; i++){
  8827. TypeNode t = templateArguments[i];
  8828. if (t == null) continue;
  8829. if (TypeIsNotFullySpecialized(t)) continue;
  8830. visibility = TypeNode.GetVisibilityIntersection(visibility, t.Flags & TypeFlags.VisibilityMask);
  8831. }
  8832. result.Flags &= ~TypeFlags.VisibilityMask;
  8833. result.Flags |= visibility;
  8834. if (this.IsGeneric) return result;
  8835. #if ExtendedRuntime
  8836. //Arrange for template instance to be emitted to module and to be recognized as a template instance when imported from module.
  8837. if (referringType == null){
  8838. if (visibility == TypeFlags.NestedPublic)
  8839. visibility = TypeFlags.Public;
  8840. else if (visibility != TypeFlags.Public)
  8841. visibility = TypeFlags.NotPublic;
  8842. module.Types.Add(result);
  8843. }else{
  8844. switch (visibility){
  8845. case TypeFlags.NestedFamANDAssem:
  8846. case TypeFlags.NestedFamily:
  8847. case TypeFlags.NestedPrivate:
  8848. if (result != referringType && this != referringType)
  8849. referringType.Members.Add(result);
  8850. else{
  8851. if (declaringType == null)
  8852. visibility = TypeFlags.NotPublic;
  8853. goto default;
  8854. }
  8855. break;
  8856. case TypeFlags.NestedAssembly:
  8857. if (declaringType == null)
  8858. visibility = TypeFlags.NotPublic;
  8859. goto default;
  8860. case TypeFlags.NestedPublic:
  8861. if (declaringType == null)
  8862. visibility = TypeFlags.Public;
  8863. goto default;
  8864. default:
  8865. if (declaringType == null){
  8866. result.DeclaringType = null;
  8867. module.Types.Add(result);
  8868. }else{
  8869. result.DeclaringType = declaringType;
  8870. declaringType.Members.Add(result);
  8871. }
  8872. break;
  8873. }
  8874. }
  8875. result.Flags &= ~TypeFlags.VisibilityMask;
  8876. result.Flags |= visibility;
  8877. AttributeList attrs = result.Attributes;
  8878. if (attrs == null) attrs = result.Attributes = new AttributeList(1);
  8879. TypeNode typeArray = CoreSystemTypes.Type.GetArrayType(1);
  8880. if (TypeNode.templateInstanceAttribute == null) {
  8881. InstanceInitializer constr = SystemTypes.TemplateInstanceAttribute.GetConstructor(CoreSystemTypes.Type, typeArray);
  8882. if (constr == null) { Debug.Fail(""); return result; }
  8883. TypeNode.templateInstanceAttribute = new MemberBinding(null, constr);
  8884. }
  8885. int n = templateArguments.Count;
  8886. TypeNode[] tArgs = new TypeNode[n];
  8887. for (int i = 0; i < n; i++) tArgs[i] = templateArguments[i];
  8888. AttributeNode attr = new AttributeNode(TypeNode.templateInstanceAttribute,
  8889. new ExpressionList(new Literal(this, CoreSystemTypes.Type), new Literal(tArgs, typeArray)));
  8890. attr.Target = AttributeTargets.Delegate|AttributeTargets.Class|AttributeTargets.Enum|AttributeTargets.Interface|AttributeTargets.Struct;
  8891. if (attrs.Count > 0 && attrs[0] == null)
  8892. attrs[0] = attr;
  8893. else
  8894. attrs.Add(attr);
  8895. #endif
  8896. return result;
  8897. }
  8898. }
  8899. protected virtual TypeNodeList GetConsolidatedTemplateArguments(){
  8900. TypeNodeList typeArgs = this.TemplateArguments;
  8901. if (this.DeclaringType == null) return typeArgs;
  8902. TypeNodeList result = this.DeclaringType.ConsolidatedTemplateArguments;
  8903. if (result == null){
  8904. if (this.DeclaringType.IsGeneric && this.DeclaringType.Template == null)
  8905. result = this.DeclaringType.ConsolidatedTemplateParameters;
  8906. if (result == null)
  8907. return typeArgs;
  8908. }
  8909. int n = typeArgs == null ? 0 : typeArgs.Count;
  8910. if (n == 0) return result;
  8911. result = result.Clone();
  8912. for (int i = 0; i < n; i++) result.Add(typeArgs[i]);
  8913. return result;
  8914. }
  8915. protected virtual TypeNodeList GetConsolidatedTemplateArguments(TypeNodeList typeArgs){
  8916. TypeNodeList result = this.ConsolidatedTemplateArguments;
  8917. if (result == null || result.Count == 0){
  8918. if (this.IsGeneric && this.Template == null)
  8919. result = this.ConsolidatedTemplateParameters;
  8920. else
  8921. return typeArgs;
  8922. }
  8923. int n = typeArgs == null ? 0 : typeArgs.Count;
  8924. if (n == 0) return result;
  8925. //^ assert typeArgs != null;
  8926. result = result.Clone();
  8927. for (int i = 0; i < n; i++) result.Add(typeArgs[i]);
  8928. return result;
  8929. }
  8930. protected virtual TypeNodeList GetConsolidatedTemplateParameters(){
  8931. TypeNodeList typeParams = this.TemplateParameters;
  8932. TypeNode declaringType = this.DeclaringType;
  8933. if (declaringType == null) return typeParams;
  8934. while (declaringType.Template != null) declaringType = declaringType.Template;
  8935. TypeNodeList result = declaringType.ConsolidatedTemplateParameters;
  8936. if (result == null) return typeParams;
  8937. int n = typeParams == null ? 0 : typeParams.Count;
  8938. if (n == 0) return result;
  8939. result = result.Clone();
  8940. for (int i = 0; i < n; i++) result.Add(typeParams[i]);
  8941. return result;
  8942. }
  8943. protected virtual TypeNodeList GetOwnTemplateArguments(TypeNodeList consolidatedTemplateArguments){
  8944. int n = this.TemplateParameters == null ? 0 : this.TemplateParameters.Count;
  8945. int m = consolidatedTemplateArguments == null ? 0 : consolidatedTemplateArguments.Count;
  8946. int k = m-n;
  8947. if (k <= 0) return consolidatedTemplateArguments;
  8948. TypeNodeList result = new TypeNodeList(n);
  8949. if (consolidatedTemplateArguments != null)
  8950. for (int i = 0; i < n; i++)
  8951. result.Add(consolidatedTemplateArguments[i+k]);
  8952. return result;
  8953. }
  8954. #if ExtendedRuntime
  8955. private static MemberBinding templateInstanceAttribute = null;
  8956. #endif
  8957. protected internal Pointer pointerType;
  8958. public virtual Pointer/*!*/ GetPointerType() {
  8959. Pointer result = this.pointerType;
  8960. if (result == null){
  8961. lock(this){
  8962. if (this.pointerType != null) return this.pointerType;
  8963. result = this.pointerType = new Pointer(this);
  8964. result.Flags &= ~TypeFlags.VisibilityMask;
  8965. result.Flags |= this.Flags & TypeFlags.VisibilityMask;
  8966. result.DeclaringModule = this.DeclaringModule;
  8967. }
  8968. }
  8969. return result;
  8970. }
  8971. protected internal Reference referenceType;
  8972. public virtual Reference/*!*/ GetReferenceType(){
  8973. Reference result = this.referenceType;
  8974. if (result == null){
  8975. lock(this){
  8976. if (this.referenceType != null) return this.referenceType;
  8977. result = this.referenceType = new Reference(this);
  8978. result.Flags &= ~TypeFlags.VisibilityMask;
  8979. result.Flags |= this.Flags & TypeFlags.VisibilityMask;
  8980. result.DeclaringModule = this.DeclaringModule;
  8981. }
  8982. }
  8983. return result;
  8984. }
  8985. //^ [Microsoft.Contracts.SpecPublic]
  8986. protected internal TrivialHashtable memberTable;
  8987. protected internal int memberCount;
  8988. /// <summary>
  8989. /// Returns a list of all the members declared directly by this type with the specified name.
  8990. /// Returns an empty list if this type has no such members.
  8991. /// </summary>
  8992. public virtual MemberList/*!*/ GetMembersNamed(Identifier name) {
  8993. if (name == null) return new MemberList(0);
  8994. MemberList members = this.Members;
  8995. int n = members == null ? 0 : members.Count;
  8996. if (n != this.memberCount || this.memberTable == null) this.UpdateMemberTable(n);
  8997. //^ assert this.memberTable != null;
  8998. MemberList result = (MemberList)this.memberTable[name.UniqueIdKey];
  8999. if (result == null){
  9000. lock(this){
  9001. result = (MemberList)this.memberTable[name.UniqueIdKey];
  9002. if (result != null) return result;
  9003. this.memberTable[name.UniqueIdKey] = (result = new MemberList());
  9004. }
  9005. }
  9006. return result;
  9007. }
  9008. /// <summary>
  9009. /// Returns the first event declared by this type with the specified name.
  9010. /// Returns null if this type has no such event.
  9011. /// </summary>
  9012. public virtual Event GetEvent(Identifier name){
  9013. MemberList members = this.GetMembersNamed(name);
  9014. for (int i = 0, n = members.Count; i < n; i++){
  9015. Event ev = members[i] as Event;
  9016. if (ev != null) return ev;
  9017. }
  9018. return null;
  9019. }
  9020. /// <summary>
  9021. /// Returns the first field declared by this type with the specified name. Returns null if this type has no such field.
  9022. /// </summary>
  9023. public virtual Field GetField(Identifier name){
  9024. MemberList members = this.GetMembersNamed(name);
  9025. for (int i = 0, n = members.Count; i < n; i++){
  9026. Field field = members[i] as Field;
  9027. if (field != null) return field;
  9028. }
  9029. return null;
  9030. }
  9031. /// <summary>
  9032. /// Returns the first method declared by this type with the specified name and parameter types. Returns null if this type has no such method.
  9033. /// </summary>
  9034. /// <returns></returns>
  9035. public virtual Method GetMethod(Identifier name, params TypeNode[] types){
  9036. return GetFirstMethod(this.GetMembersNamed(name), types);
  9037. }
  9038. private static Method GetFirstMethod(MemberList members, params TypeNode[] types){
  9039. if (members == null) return null;
  9040. int m = types == null ? 0 : types.Length;
  9041. TypeNodeList typeNodes = m == 0 ? null : new TypeNodeList(types);
  9042. for (int i = 0, n = members.Count; i < n; i++){
  9043. Method meth = members[i] as Method;
  9044. if (meth == null) continue;
  9045. if (meth.ParameterTypesMatchStructurally(typeNodes)) return meth;
  9046. }
  9047. return null;
  9048. }
  9049. public virtual MethodList GetMethods(Identifier name, params TypeNode[] types) {
  9050. return GetMethods(this.GetMembersNamed(name), types);
  9051. }
  9052. private static MethodList GetMethods(MemberList members, params TypeNode[] types) {
  9053. if (members == null) return null;
  9054. int m = types == null ? 0 : types.Length;
  9055. MethodList result = new MethodList();
  9056. TypeNodeList typeNodes = m == 0 ? null : new TypeNodeList(types);
  9057. for (int i = 0, n = members.Count; i < n; i++) {
  9058. Method meth = members[i] as Method;
  9059. if (meth == null) continue;
  9060. if (meth.ParameterTypesMatchStructurally(typeNodes)) result.Add(meth);
  9061. }
  9062. return result;
  9063. }
  9064. public Method GetMatchingMethod(Method method) {
  9065. if (method == null || method.Name == null) return null;
  9066. MemberList members = this.GetMembersNamed(method.Name);
  9067. for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++){
  9068. Method m = members[i] as Method;
  9069. if (m == null) continue;
  9070. if (m.ParametersMatchStructurally(method.Parameters)) return m;
  9071. }
  9072. return null;
  9073. }
  9074. /// <summary>
  9075. /// Returns the first nested type declared by this type with the specified name. Returns null if this type has no such nested type.
  9076. /// </summary>
  9077. public virtual TypeNode GetNestedType(Identifier name){
  9078. if (name == null) return null;
  9079. if (this.members != null){
  9080. MemberList members = this.GetMembersNamed(name);
  9081. for (int i = 0, n = members.Count; i < n; i++){
  9082. TypeNode type = members[i] as TypeNode;
  9083. if (type != null) return type;
  9084. }
  9085. return null;
  9086. }
  9087. TypeNodeList nestedTypes = this.NestedTypes;
  9088. for (int i = 0, n = nestedTypes == null ? 0 : nestedTypes.Count; i < n; i++) {
  9089. TypeNode type = nestedTypes[i];
  9090. if (type != null && type.Name.UniqueIdKey == name.UniqueIdKey) return type;
  9091. }
  9092. return null;
  9093. }
  9094. protected internal TypeNodeList nestedTypes;
  9095. public virtual TypeNodeList NestedTypes{
  9096. get{
  9097. if (this.nestedTypes != null && (this.members == null || this.members.Count == this.memberCount))
  9098. return this.nestedTypes;
  9099. if (this.ProvideNestedTypes != null && this.ProviderHandle != null){
  9100. lock (Module.GlobalLock){
  9101. this.ProvideNestedTypes(this, this.ProviderHandle);
  9102. }
  9103. }else{
  9104. MemberList members = this.Members;
  9105. TypeNodeList nestedTypes = new TypeNodeList();
  9106. for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++){
  9107. TypeNode nt = members[i] as TypeNode;
  9108. if (nt == null) continue;
  9109. nestedTypes.Add(nt);
  9110. }
  9111. this.nestedTypes = nestedTypes;
  9112. }
  9113. return this.nestedTypes;
  9114. }
  9115. set{
  9116. this.nestedTypes = value;
  9117. }
  9118. }
  9119. /// <summary>
  9120. /// Returns the first property declared by this type with the specified name and parameter types. Returns null if this type has no such property.
  9121. /// </summary>
  9122. public virtual Property GetProperty(Identifier name, params TypeNode[] types){
  9123. return GetProperty(this.GetMembersNamed(name), types);
  9124. }
  9125. private static Property GetProperty(MemberList members, params TypeNode[] types){
  9126. if (members == null) return null;
  9127. int m = types == null ? 0 : types.Length;
  9128. TypeNodeList typeNodes = m == 0 ? null : new TypeNodeList(types);
  9129. for (int i = 0, n = members.Count; i < n; i++){
  9130. Property prop = members[i] as Property;
  9131. if (prop == null) continue;
  9132. if (prop.ParameterTypesMatch(typeNodes)) return prop;
  9133. }
  9134. return null;
  9135. }
  9136. #if !MinimalReader
  9137. protected internal MemberList explicitCoercionMethods;
  9138. public virtual MemberList ExplicitCoercionMethods{
  9139. get{
  9140. if (this.Members.Count != this.memberCount) this.explicitCoercionMethods = null;
  9141. if (this.explicitCoercionMethods != null) return this.explicitCoercionMethods;
  9142. lock(this){
  9143. if (this.explicitCoercionMethods != null) return this.explicitCoercionMethods;
  9144. return this.explicitCoercionMethods = TypeNode.WeedOutNonSpecialMethods(this.GetMembersNamed(StandardIds.opExplicit), MethodFlags.SpecialName);
  9145. }
  9146. }
  9147. }
  9148. protected internal MemberList implicitCoercionMethods;
  9149. public virtual MemberList ImplicitCoercionMethods{
  9150. get{
  9151. if (this.Members.Count != this.memberCount) this.implicitCoercionMethods = null;
  9152. if (this.implicitCoercionMethods != null) return this.implicitCoercionMethods;
  9153. lock(this){
  9154. if (this.implicitCoercionMethods != null) return this.implicitCoercionMethods;
  9155. return this.implicitCoercionMethods = TypeNode.WeedOutNonSpecialMethods(this.GetMembersNamed(StandardIds.opImplicit), MethodFlags.SpecialName);
  9156. }
  9157. }
  9158. }
  9159. protected readonly static Method MethodDoesNotExist = new Method();
  9160. protected internal TrivialHashtable explicitCoercionFromTable;
  9161. public virtual Method GetExplicitCoercionFromMethod(TypeNode sourceType){
  9162. if (sourceType == null) return null;
  9163. Method result = null;
  9164. if (this.explicitCoercionFromTable != null)
  9165. result = (Method)this.explicitCoercionFromTable[sourceType.UniqueKey];
  9166. if (result == TypeNode.MethodDoesNotExist) return null;
  9167. if (result != null) return result;
  9168. lock(this){
  9169. if (this.explicitCoercionFromTable != null)
  9170. result = (Method)this.explicitCoercionFromTable[sourceType.UniqueKey];
  9171. if (result == TypeNode.MethodDoesNotExist) return null;
  9172. if (result != null) return result;
  9173. MemberList coercions = this.ExplicitCoercionMethods;
  9174. for (int i = 0, n = coercions.Count; i < n; i++){
  9175. Method m = (Method)coercions[i];
  9176. if (sourceType == m.Parameters[0].Type){result = m; break;}
  9177. }
  9178. if (this.explicitCoercionFromTable == null)
  9179. this.explicitCoercionFromTable = new TrivialHashtable();
  9180. if (result == null)
  9181. this.explicitCoercionFromTable[sourceType.UniqueKey] = TypeNode.MethodDoesNotExist;
  9182. else
  9183. this.explicitCoercionFromTable[sourceType.UniqueKey] = result;
  9184. return result;
  9185. }
  9186. }
  9187. protected internal TrivialHashtable explicitCoercionToTable;
  9188. public virtual Method GetExplicitCoercionToMethod(TypeNode targetType){
  9189. if (targetType == null) return null;
  9190. Method result = null;
  9191. if (this.explicitCoercionToTable != null)
  9192. result = (Method)this.explicitCoercionToTable[targetType.UniqueKey];
  9193. if (result == TypeNode.MethodDoesNotExist) return null;
  9194. if (result != null) return result;
  9195. lock(this){
  9196. if (this.explicitCoercionToTable != null)
  9197. result = (Method)this.explicitCoercionToTable[targetType.UniqueKey];
  9198. if (result == TypeNode.MethodDoesNotExist) return null;
  9199. if (result != null) return result;
  9200. MemberList coercions = this.ExplicitCoercionMethods;
  9201. for (int i = 0, n = coercions.Count; i < n; i++){
  9202. Method m = (Method)coercions[i];
  9203. if (m.ReturnType == targetType){result = m; break;}
  9204. }
  9205. if (this.explicitCoercionToTable == null)
  9206. this.explicitCoercionToTable = new TrivialHashtable();
  9207. if (result == null)
  9208. this.explicitCoercionToTable[targetType.UniqueKey] = TypeNode.MethodDoesNotExist;
  9209. else
  9210. this.explicitCoercionToTable[targetType.UniqueKey] = result;
  9211. }
  9212. return result;
  9213. }
  9214. protected internal TrivialHashtable implicitCoercionFromTable;
  9215. public virtual Method GetImplicitCoercionFromMethod(TypeNode sourceType){
  9216. if (sourceType == null) return null;
  9217. Method result = null;
  9218. if (this.implicitCoercionFromTable != null)
  9219. result = (Method)this.implicitCoercionFromTable[sourceType.UniqueKey];
  9220. if (result == TypeNode.MethodDoesNotExist) return null;
  9221. if (result != null) return result;
  9222. lock(this){
  9223. if (this.implicitCoercionFromTable != null)
  9224. result = (Method)this.implicitCoercionFromTable[sourceType.UniqueKey];
  9225. if (result == TypeNode.MethodDoesNotExist) return null;
  9226. if (result != null) return result;
  9227. MemberList coercions = this.ImplicitCoercionMethods;
  9228. for (int i = 0, n = coercions.Count; i < n; i++){
  9229. Method m = (Method)coercions[i];
  9230. if (sourceType.IsStructurallyEquivalentTo(TypeNode.StripModifiers(m.Parameters[0].Type))){result = m; break;}
  9231. }
  9232. if (this.implicitCoercionFromTable == null)
  9233. this.implicitCoercionFromTable = new TrivialHashtable();
  9234. if (result == null)
  9235. this.implicitCoercionFromTable[sourceType.UniqueKey] = TypeNode.MethodDoesNotExist;
  9236. else
  9237. this.implicitCoercionFromTable[sourceType.UniqueKey] = result;
  9238. return result;
  9239. }
  9240. }
  9241. protected internal TrivialHashtable implicitCoercionToTable;
  9242. public virtual Method GetImplicitCoercionToMethod(TypeNode targetType){
  9243. if (targetType == null) return null;
  9244. Method result = null;
  9245. if (this.implicitCoercionToTable != null)
  9246. result = (Method)this.implicitCoercionToTable[targetType.UniqueKey];
  9247. if (result == TypeNode.MethodDoesNotExist) return null;
  9248. if (result != null) return result;
  9249. lock(this){
  9250. if (this.implicitCoercionToTable != null)
  9251. result = (Method)this.implicitCoercionToTable[targetType.UniqueKey];
  9252. if (result == TypeNode.MethodDoesNotExist) return null;
  9253. if (result != null) return result;
  9254. MemberList coercions = this.ImplicitCoercionMethods;
  9255. for (int i = 0, n = coercions.Count; i < n; i++){
  9256. Method m = (Method)coercions[i];
  9257. if (m.ReturnType == targetType){result = m; break;}
  9258. }
  9259. if (this.implicitCoercionToTable == null)
  9260. this.implicitCoercionToTable = new TrivialHashtable();
  9261. if (result == null)
  9262. this.implicitCoercionToTable[targetType.UniqueKey] = TypeNode.MethodDoesNotExist;
  9263. else
  9264. this.implicitCoercionToTable[targetType.UniqueKey] = result;
  9265. return result;
  9266. }
  9267. }
  9268. protected Method opFalse;
  9269. public virtual Method GetOpFalse(){
  9270. Method result = this.opFalse;
  9271. if (result == TypeNode.MethodDoesNotExist) return null;
  9272. if (result != null) return result;
  9273. MemberList members = this.Members; //evaluate for side effect
  9274. if (members != null) members = null;
  9275. lock(this){
  9276. result = this.opFalse;
  9277. if (result == TypeNode.MethodDoesNotExist) return null;
  9278. if (result != null) return result;
  9279. TypeNode t = this;
  9280. while (t != null){
  9281. MemberList opFalses = t.GetMembersNamed(StandardIds.opFalse);
  9282. if (opFalses != null)
  9283. for (int i = 0, n = opFalses.Count; i < n; i++){
  9284. Method opFalse = opFalses[i] as Method;
  9285. if (opFalse == null) continue;
  9286. if (!opFalse.IsSpecialName || !opFalse.IsStatic || !opFalse.IsPublic || opFalse.ReturnType != CoreSystemTypes.Boolean ||
  9287. opFalse.Parameters == null || opFalse.Parameters.Count != 1) continue;
  9288. return this.opFalse = opFalse;
  9289. }
  9290. t = t.BaseType;
  9291. }
  9292. this.opFalse = TypeNode.MethodDoesNotExist;
  9293. return null;
  9294. }
  9295. }
  9296. protected Method opTrue;
  9297. public virtual Method GetOpTrue(){
  9298. Method result = this.opTrue;
  9299. if (result == TypeNode.MethodDoesNotExist) return null;
  9300. if (result != null) return result;
  9301. MemberList members = this.Members; //evaluate for side effect
  9302. if (members != null) members = null;
  9303. lock(this){
  9304. result = this.opTrue;
  9305. if (result == TypeNode.MethodDoesNotExist) return null;
  9306. if (result != null) return result;
  9307. TypeNode t = this;
  9308. while (t != null){
  9309. MemberList opTrues = t.GetMembersNamed(StandardIds.opTrue);
  9310. if (opTrues != null)
  9311. for (int i = 0, n = opTrues.Count; i < n; i++){
  9312. Method opTrue = opTrues[i] as Method;
  9313. if (opTrue == null) continue;
  9314. if (!opTrue.IsSpecialName || !opTrue.IsStatic || !opTrue.IsPublic || opTrue.ReturnType != CoreSystemTypes.Boolean ||
  9315. opTrue.Parameters == null || opTrue.Parameters.Count != 1) continue;
  9316. return this.opTrue = opTrue;
  9317. }
  9318. t = t.BaseType;
  9319. }
  9320. this.opTrue = TypeNode.MethodDoesNotExist;
  9321. return null;
  9322. }
  9323. }
  9324. #endif
  9325. #if !NoReflection
  9326. private static Hashtable typeMap; //contains weak references
  9327. /// <summary>
  9328. /// Gets a TypeNode instance corresponding to the given System.Type instance.
  9329. /// </summary>
  9330. /// <param name="type">A runtime type.</param>
  9331. /// <returns>A TypeNode instance.</returns>
  9332. public static TypeNode GetTypeNode(System.Type type){
  9333. if (type == null) return null;
  9334. Hashtable typeMap = TypeNode.typeMap;
  9335. if (typeMap == null) TypeNode.typeMap = typeMap = Hashtable.Synchronized(new Hashtable());
  9336. TypeNode result = null;
  9337. WeakReference wr = (WeakReference)typeMap[type];
  9338. if (wr != null){
  9339. result = wr.Target as TypeNode;
  9340. if (result == Class.DoesNotExist) return null;
  9341. if (result != null) return result;
  9342. }
  9343. #if WHIDBEY
  9344. if (type.IsGenericType && !type.IsGenericTypeDefinition){
  9345. try{
  9346. TypeNode template = TypeNode.GetTypeNode(type.GetGenericTypeDefinition());
  9347. if (template == null) return null;
  9348. TypeNodeList templateArguments = new TypeNodeList();
  9349. foreach (Type arg in type.GetGenericArguments())
  9350. templateArguments.Add(TypeNode.GetTypeNode(arg));
  9351. return template.GetGenericTemplateInstance(template.DeclaringModule, templateArguments);
  9352. }catch{
  9353. //TODO: log error
  9354. return null;
  9355. }
  9356. }
  9357. if (type.IsGenericParameter){
  9358. try{
  9359. int parIndx = type.GenericParameterPosition;
  9360. System.Reflection.MethodInfo mi = type.DeclaringMethod as System.Reflection.MethodInfo;
  9361. if (mi != null){
  9362. Method m = Method.GetMethod(mi);
  9363. if (m == null) return null;
  9364. if (m.TemplateParameters != null && m.TemplateParameters.Count > parIndx)
  9365. return m.TemplateParameters[parIndx];
  9366. }else{
  9367. System.Type ti = type.DeclaringType;
  9368. TypeNode t = TypeNode.GetTypeNode(ti);
  9369. if (t == null) return null;
  9370. if (t.TemplateParameters != null && t.TemplateParameters.Count > parIndx)
  9371. return t.TemplateParameters[parIndx];
  9372. }
  9373. return null;
  9374. }catch{
  9375. //TODO: log error
  9376. return null;
  9377. }
  9378. }
  9379. #endif
  9380. if (type.HasElementType){
  9381. TypeNode elemType = TypeNode.GetTypeNode(type.GetElementType());
  9382. if (elemType == null) return null;
  9383. if (type.IsArray)
  9384. result = elemType.GetArrayType(type.GetArrayRank());
  9385. else if (type.IsByRef)
  9386. result = elemType.GetReferenceType();
  9387. else if (type.IsPointer)
  9388. result = elemType.GetPointerType();
  9389. else{
  9390. Debug.Assert(false);
  9391. result = null;
  9392. }
  9393. }else if (type.DeclaringType != null){
  9394. TypeNode dType = TypeNode.GetTypeNode(type.DeclaringType);
  9395. if (dType == null) return null;
  9396. result = dType.GetNestedType(Identifier.For(type.Name));
  9397. }else{
  9398. AssemblyNode assem = AssemblyNode.GetAssembly(type.Assembly);
  9399. if (assem != null){
  9400. result = assem.GetType(Identifier.For(type.Namespace), Identifier.For(type.Name));
  9401. }
  9402. }
  9403. if (result == null)
  9404. typeMap[type] = new WeakReference(Class.DoesNotExist);
  9405. else
  9406. typeMap[type] = new WeakReference(result);
  9407. return result;
  9408. }
  9409. protected internal Type runtimeType;
  9410. /// <summary>
  9411. /// Gets a System.Type instance corresponding to this type. The assembly containin this type must be normalized
  9412. /// and must have a location on disk or must have been loaded via AssemblyNode.GetRuntimeAssembly.
  9413. /// </summary>
  9414. /// <returns>A System.Type instance. (A runtime type.)</returns>
  9415. public virtual Type GetRuntimeType(){
  9416. if (this.runtimeType == null){
  9417. lock(this){
  9418. if (this.runtimeType != null) return this.runtimeType;
  9419. #if WHIDBEY
  9420. if (this.IsGeneric && this.Template != null){
  9421. try {
  9422. TypeNode rootTemplate = this.Template;
  9423. while (rootTemplate.Template != null)
  9424. rootTemplate = rootTemplate.Template;
  9425. Type genType = rootTemplate.GetRuntimeType();
  9426. if (genType == null) return null;
  9427. TypeNodeList args = this.ConsolidatedTemplateArguments;
  9428. Type[] arguments = new Type[args.Count];
  9429. for (int i = 0; i < args.Count; i++) arguments[i] = args[i].GetRuntimeType();
  9430. return genType.MakeGenericType(arguments);
  9431. }catch{
  9432. //TODO: add error to metadata import errors if type is imported
  9433. return null;
  9434. }
  9435. }
  9436. #endif
  9437. if (this.DeclaringType != null){
  9438. Type dt = this.DeclaringType.GetRuntimeType();
  9439. if (dt != null){
  9440. System.Reflection.BindingFlags flags = System.Reflection.BindingFlags.DeclaredOnly;
  9441. if (this.IsPublic) flags |= System.Reflection.BindingFlags.Public; else flags |= System.Reflection.BindingFlags.NonPublic;
  9442. this.runtimeType = dt.GetNestedType(this.Name.ToString(), flags);
  9443. }
  9444. }else if (this.DeclaringModule != null && this.DeclaringModule.IsNormalized && this.DeclaringModule.ContainingAssembly != null){
  9445. System.Reflection.Assembly runtimeAssembly = this.DeclaringModule.ContainingAssembly.GetRuntimeAssembly();
  9446. if (runtimeAssembly != null)
  9447. this.runtimeType = runtimeAssembly.GetType(this.FullName, false);
  9448. }
  9449. }
  9450. }
  9451. return this.runtimeType;
  9452. }
  9453. #endif
  9454. public static TypeFlags GetVisibilityIntersection(TypeFlags vis1, TypeFlags vis2){
  9455. switch (vis2){
  9456. case TypeFlags.Public:
  9457. case TypeFlags.NestedPublic:
  9458. return vis1;
  9459. case TypeFlags.NotPublic:
  9460. case TypeFlags.NestedAssembly:
  9461. switch (vis1){
  9462. case TypeFlags.Public:
  9463. return vis2;
  9464. case TypeFlags.NestedPublic:
  9465. case TypeFlags.NestedFamORAssem:
  9466. return TypeFlags.NestedAssembly;
  9467. case TypeFlags.NestedFamily:
  9468. return TypeFlags.NestedFamANDAssem;
  9469. default:
  9470. return vis1;
  9471. }
  9472. case TypeFlags.NestedFamANDAssem:
  9473. switch (vis1){
  9474. case TypeFlags.Public:
  9475. case TypeFlags.NestedPublic:
  9476. case TypeFlags.NestedFamORAssem:
  9477. case TypeFlags.NestedFamily:
  9478. return TypeFlags.NestedFamANDAssem;
  9479. default:
  9480. return vis1;
  9481. }
  9482. case TypeFlags.NestedFamORAssem:
  9483. switch (vis1){
  9484. case TypeFlags.Public:
  9485. case TypeFlags.NestedPublic:
  9486. return TypeFlags.NestedFamORAssem;
  9487. default:
  9488. return vis1;
  9489. }
  9490. case TypeFlags.NestedFamily:
  9491. switch (vis1){
  9492. case TypeFlags.Public:
  9493. case TypeFlags.NestedPublic:
  9494. case TypeFlags.NestedFamORAssem:
  9495. return TypeFlags.NestedFamily;
  9496. case TypeFlags.NestedAssembly:
  9497. return TypeFlags.NestedFamANDAssem;
  9498. default:
  9499. return vis1;
  9500. }
  9501. default:
  9502. return TypeFlags.NestedPrivate;
  9503. }
  9504. }
  9505. private TrivialHashtable explicitInterfaceImplementations;
  9506. public bool ImplementsExplicitly(Method method){
  9507. if (method == null) return false;
  9508. TrivialHashtable explicitInterfaceImplementations = this.explicitInterfaceImplementations;
  9509. if (explicitInterfaceImplementations == null){
  9510. MemberList members = this.Members;
  9511. lock(this){
  9512. if ((explicitInterfaceImplementations = this.explicitInterfaceImplementations) == null){
  9513. explicitInterfaceImplementations = this.explicitInterfaceImplementations = new TrivialHashtable();
  9514. for (int i = 0, n = members.Count; i < n; i++){
  9515. Method m = members[i] as Method;
  9516. if (m == null) continue;
  9517. MethodList implementedInterfaceMethods = m.ImplementedInterfaceMethods;
  9518. if (implementedInterfaceMethods != null)
  9519. for (int j = 0, k = implementedInterfaceMethods.Count; j < k; j++){
  9520. Method im = implementedInterfaceMethods[j];
  9521. if (im == null) continue;
  9522. explicitInterfaceImplementations[im.UniqueKey] = m;
  9523. }
  9524. }
  9525. }
  9526. }
  9527. }
  9528. return explicitInterfaceImplementations[method.UniqueKey] != null;
  9529. }
  9530. public Method ExplicitImplementation(Method method)
  9531. {
  9532. if (ImplementsExplicitly(method)) return (Method)explicitInterfaceImplementations[method.UniqueKey];
  9533. return null;
  9534. }
  9535. #if !MinimalReader
  9536. internal bool ImplementsMethod(Method meth, bool checkPublic){
  9537. return this.GetImplementingMethod(meth, checkPublic) != null;
  9538. }
  9539. public Method GetImplementingMethod(Method meth, bool checkPublic){
  9540. if (meth == null) return null;
  9541. MemberList mems = this.GetMembersNamed(meth.Name);
  9542. for (int j = 0, m = mems == null ? 0 : mems.Count; j < m; j++){
  9543. Method locM = mems[j] as Method;
  9544. if (locM == null || !locM.IsVirtual || (checkPublic && !locM.IsPublic)) continue;
  9545. if ((locM.ReturnType != meth.ReturnType && !(locM.ReturnType != null && locM.ReturnType.IsStructurallyEquivalentTo(meth.ReturnType))) ||
  9546. !locM.ParametersMatchStructurally(meth.Parameters)) continue;
  9547. return locM;
  9548. }
  9549. if (checkPublic && this.BaseType != null)
  9550. return this.BaseType.GetImplementingMethod(meth, true);
  9551. return null;
  9552. }
  9553. #endif
  9554. /// <summary>
  9555. /// Returns true if the CLR CTS allows a value of this type may be assigned to a variable of the target type (possibly after boxing),
  9556. /// either because the target type is the same or a base type, or because the target type is an interface implemented by this type or the implementor of this type,
  9557. /// or because this type and the target type are zero based single dimensional arrays with assignment compatible reference element types
  9558. /// </summary>
  9559. public virtual bool IsAssignableTo(TypeNode targetType){
  9560. if (this == CoreSystemTypes.Void) return false;
  9561. if (targetType == this) return true;
  9562. if (this == CoreSystemTypes.Object) return false;
  9563. if (targetType == CoreSystemTypes.Object || this.IsStructurallyEquivalentTo(targetType) ||
  9564. this.BaseType != null && (this.BaseType.IsAssignableTo(targetType)))
  9565. return true;
  9566. if (this.BaseType != null && this.ConsolidatedTemplateParameters != null && this.BaseType.Template != null && this.BaseType.Template.IsAssignableTo(targetType))
  9567. return true; //When seeing if one template is assignable to another, be sure to strip off template instances along the inheritance chain
  9568. InterfaceList interfaces = this.Interfaces;
  9569. if (interfaces == null) return false;
  9570. for (int i = 0, n = interfaces.Count; i < n; i++){
  9571. Interface iface = interfaces[i];
  9572. if (iface == null) continue;
  9573. if (iface.IsAssignableTo(targetType)) return true;
  9574. if (iface.Template != null && this.ConsolidatedTemplateParameters != null && iface.Template.IsAssignableTo(targetType))
  9575. return true; //When seeing if one template is assignable to another, be sure to strip off template instances along the inheritance chain
  9576. }
  9577. return false;
  9578. }
  9579. /// <summary>
  9580. /// Returns true if this type is assignable to some instance of the given template.
  9581. /// </summary>
  9582. public virtual bool IsAssignableToInstanceOf(TypeNode targetTemplate){
  9583. if (this == CoreSystemTypes.Void || targetTemplate == null) return false;
  9584. if (targetTemplate.IsStructurallyEquivalentTo(this.Template == null ? this : this.Template) ||
  9585. this.BaseType != null && (this.BaseType.IsAssignableToInstanceOf(targetTemplate) ||
  9586. this.BaseType.Template != null && this.BaseType.Template.IsAssignableToInstanceOf(targetTemplate))) return true;
  9587. InterfaceList interfaces = this.Interfaces;
  9588. if (interfaces == null) return false;
  9589. for (int i = 0, n = interfaces.Count; i < n; i++) {
  9590. Interface iface = interfaces[i];
  9591. if (iface == null) continue;
  9592. if (iface.IsAssignableToInstanceOf(targetTemplate)) return true;
  9593. }
  9594. return false;
  9595. }
  9596. /// <summary>
  9597. /// Returns true if this type is assignable to some instance of the given template.
  9598. /// </summary>
  9599. public virtual bool IsAssignableToInstanceOf(TypeNode targetTemplate, out TypeNodeList templateArguments){
  9600. templateArguments = null;
  9601. if (this == CoreSystemTypes.Void || targetTemplate == null) return false;
  9602. if (targetTemplate == this.Template){
  9603. templateArguments = this.TemplateArguments;
  9604. return true;
  9605. }
  9606. if (this != CoreSystemTypes.Object && this.BaseType != null && this.BaseType.IsAssignableToInstanceOf(targetTemplate, out templateArguments)) return true;
  9607. InterfaceList interfaces = this.Interfaces;
  9608. if (interfaces == null) return false;
  9609. for (int i = 0, n = interfaces.Count; i < n; i++) {
  9610. Interface iface = interfaces[i];
  9611. if (iface == null) continue;
  9612. if (iface.IsAssignableToInstanceOf(targetTemplate, out templateArguments)) return true;
  9613. }
  9614. return false;
  9615. }
  9616. /// <summary>
  9617. /// Returns true if otherType is the base class of this type or if the base class of this type is derived from otherType.
  9618. /// </summary>
  9619. public virtual bool IsDerivedFrom(TypeNode otherType){
  9620. if (otherType == null) return false;
  9621. TypeNode baseType = this.BaseType;
  9622. while (baseType != null){
  9623. if (baseType == otherType) return true;
  9624. baseType = baseType.BaseType;
  9625. }
  9626. return false;
  9627. }
  9628. #if !MinimalReader
  9629. // Not thread safe code...
  9630. bool isCheckingInheritedFrom = false;
  9631. public virtual bool IsInheritedFrom(TypeNode otherType) {
  9632. if (otherType == null) return false;
  9633. if (this == otherType) return true;
  9634. bool result = false;
  9635. if (this.isCheckingInheritedFrom)
  9636. goto done;
  9637. this.isCheckingInheritedFrom = true;
  9638. if (this.Template != null) {
  9639. result = this.Template.IsInheritedFrom(otherType);
  9640. goto done;
  9641. }
  9642. if (otherType.Template != null) {
  9643. otherType = otherType.Template;
  9644. }
  9645. TypeNode baseType = this.BaseType;
  9646. if (baseType != null && baseType.IsInheritedFrom(otherType)) {
  9647. result = true;
  9648. goto done;
  9649. }
  9650. InterfaceList interfaces = this.Interfaces;
  9651. if (interfaces == null) goto done;
  9652. for (int i = 0, n = interfaces.Count; i < n; i++) {
  9653. Interface iface = interfaces[i];
  9654. if (iface == null) continue;
  9655. if (iface.IsInheritedFrom(otherType)) {
  9656. result = true;
  9657. goto done;
  9658. }
  9659. }
  9660. done:
  9661. this.isCheckingInheritedFrom = false;
  9662. return result;
  9663. }
  9664. #endif
  9665. public virtual bool IsStructurallyEquivalentTo(TypeNode type){
  9666. if (null == (object)type) return false;
  9667. if (this == type) return true;
  9668. if (this.Template == (object)null || type.Template == (object)null) {
  9669. if (((object)this) == (object)type.Template || ((object)this.Template) == (object)type) return true;
  9670. Identifier thisName = this.Template == null ? this.Name : this.Template.Name;
  9671. Identifier typeName = type.Template == null ? type.Name : type.Template.Name;
  9672. if (thisName == null || typeName == null || thisName.UniqueIdKey != typeName.UniqueIdKey) return false;
  9673. if (this.NodeType != type.NodeType) return false;
  9674. if (this.DeclaringType == null || type.DeclaringType == null) return false;
  9675. }
  9676. if (this.TemplateArguments == null || type.TemplateArguments == null){
  9677. if (this.DeclaringType != null && (this.TemplateArguments == null || this.TemplateArguments.Count == 0) &&
  9678. (type.TemplateArguments == null || type.TemplateArguments.Count == 0))
  9679. return this.DeclaringType.IsStructurallyEquivalentTo(type.DeclaringType);
  9680. return false;
  9681. }
  9682. int n = this.TemplateArguments.Count; if (n != type.TemplateArguments.Count) return false;
  9683. if (this.Template != type.Template && !this.Template.IsStructurallyEquivalentTo(type.Template)) return false;
  9684. for (int i = 0; i < n; i++){
  9685. TypeNode ta1 = this.TemplateArguments[i];
  9686. TypeNode ta2 = type.TemplateArguments[i];
  9687. if (null == (object)ta1 || null == (object)ta2) return false;
  9688. if (ta1 == ta2) continue;
  9689. if (!ta1.IsStructurallyEquivalentTo(ta2)) return false;
  9690. }
  9691. if (this.DeclaringType != null)
  9692. return this.DeclaringType.IsStructurallyEquivalentTo(type.DeclaringType);
  9693. return true;
  9694. }
  9695. public virtual bool IsStructurallyEquivalentList(TypeNodeList list1, TypeNodeList list2){
  9696. if (list1 == null) return list2 == null;
  9697. if (list2 == null) return false;
  9698. int n = list1.Count; if (list2.Count != n) return false;
  9699. for (int i = 0; i < n; i++){
  9700. TypeNode t1 = list1[i];
  9701. TypeNode t2 = list2[i];
  9702. if (null == (object)t1 || null == (object)t2) return false;
  9703. if (t1 == t2) continue;
  9704. if (!t1.IsStructurallyEquivalentTo(t2)) return false;
  9705. }
  9706. return true;
  9707. }
  9708. public static TypeNode StripModifiers(TypeNode type)
  9709. //^ ensures t != null ==> result != null;
  9710. {
  9711. for (TypeModifier tmod = type as TypeModifier; tmod != null; tmod = type as TypeModifier)
  9712. type = tmod.ModifiedType;
  9713. // Don't strip under pointers or refs. We only strip top-level modifiers.
  9714. return type;
  9715. }
  9716. #if !MinimalReader
  9717. public static TypeNode DeepStripModifiers(TypeNode type)
  9718. //^ ensures type != null ==> result != null;
  9719. {
  9720. // strip off any outer type modifiers
  9721. for (TypeModifier tmod = type as TypeModifier; tmod != null; tmod = type as TypeModifier)
  9722. type = tmod.ModifiedType;
  9723. // For arrays and references, strip the inner type and then reconstruct the array or reference
  9724. ArrayType ar = type as ArrayType;
  9725. if (ar != null) {
  9726. TypeNode t = TypeNode.DeepStripModifiers(ar.ElementType);
  9727. return t.GetArrayType(1);
  9728. }
  9729. Reference rt = type as Reference;
  9730. if (rt != null) {
  9731. TypeNode t = TypeNode.DeepStripModifiers(rt.ElementType);
  9732. return t.GetReferenceType();
  9733. }
  9734. return type;
  9735. }
  9736. /// <summary>
  9737. /// Strip the given modifier from the type, modulo substructures that are instantiated with respect
  9738. /// to the given template type. In other words, travers type and templateType in parallel, stripping common
  9739. /// non-null modifiers, but stop when reaching a type variable in the template type.
  9740. /// <param name="type">Type to be stripped</param>
  9741. /// <param name="modifiers">Modifiers to strip off</param>
  9742. /// <param name="templateType">Template bounding the stripping of type. Passing null for the templateType performs a full DeepStrip</param>
  9743. /// </summary>
  9744. public static TypeNode DeepStripModifiers(TypeNode type, TypeNode templateType, params TypeNode[] modifiers) {
  9745. if (templateType == null) return DeepStripModifiers(type, modifiers);
  9746. if (templateType is ITypeParameter) return type;
  9747. // strip off inner modifiers then outer type modifier if it matches
  9748. OptionalModifier optmod = type as OptionalModifier;
  9749. if (optmod != null) {
  9750. OptionalModifier optmodtemplate = (OptionalModifier)templateType; // must be in sync
  9751. TypeNode t = TypeNode.DeepStripModifiers(optmod.ModifiedType, optmodtemplate.ModifiedType, modifiers);
  9752. for (int i = 0; i < modifiers.Length; ++i) {
  9753. if (optmod.Modifier == modifiers[i]) {
  9754. // strip it
  9755. return t;
  9756. }
  9757. }
  9758. return OptionalModifier.For(optmod.Modifier, t);
  9759. }
  9760. RequiredModifier reqmod = type as RequiredModifier;
  9761. if (reqmod != null) {
  9762. RequiredModifier reqmodtemplate = (RequiredModifier)templateType; // must be in sync
  9763. TypeNode t = TypeNode.DeepStripModifiers(reqmod.ModifiedType, reqmodtemplate.ModifiedType, modifiers);
  9764. for (int i = 0; i < modifiers.Length; ++i) {
  9765. if (reqmod.Modifier == modifiers[i]) {
  9766. // strip it
  9767. return t;
  9768. }
  9769. }
  9770. return RequiredModifier.For(reqmod.Modifier, t);
  9771. }
  9772. // For arrays and references, strip the inner type and then reconstruct the array or reference
  9773. ArrayType ar = type as ArrayType;
  9774. if (ar != null) {
  9775. ArrayType artemplate = (ArrayType)templateType;
  9776. TypeNode t = TypeNode.DeepStripModifiers(ar.ElementType, artemplate.ElementType, modifiers);
  9777. return t.GetArrayType(1);
  9778. }
  9779. Reference rt = type as Reference;
  9780. if (rt != null) {
  9781. Reference rttemplate = (Reference)templateType;
  9782. TypeNode t = TypeNode.DeepStripModifiers(rt.ElementType, rttemplate.ElementType, modifiers);
  9783. return t.GetReferenceType();
  9784. }
  9785. // strip template arguments
  9786. if (type.Template != null && type.TemplateArguments != null && type.TemplateArguments.Count > 0) {
  9787. TypeNodeList strippedArgs = new TypeNodeList(type.TemplateArguments.Count);
  9788. for (int i = 0; i < type.TemplateArguments.Count; i++) {
  9789. //FIX: bug introduced by checkin 16494
  9790. //templateType may have type parameters in either the TemplateArguments position or the templateParameters position.
  9791. //This may indicate an inconsistency in the template instantiation representation elsewhere.
  9792. TypeNodeList templateTypeArgs = templateType.TemplateArguments != null ? templateType.TemplateArguments : templateType.TemplateParameters;
  9793. strippedArgs.Add(DeepStripModifiers(type.TemplateArguments[i], templateTypeArgs[i], modifiers));
  9794. }
  9795. return type.Template.GetTemplateInstance(type, strippedArgs);
  9796. }
  9797. return type;
  9798. }
  9799. public static TypeNode DeepStripModifiers(TypeNode type, params TypeNode[] modifiers) {
  9800. // strip off inner modifiers then outer type modifier if it matches
  9801. OptionalModifier optmod = type as OptionalModifier;
  9802. if (optmod != null) {
  9803. TypeNode t = TypeNode.DeepStripModifiers(optmod.ModifiedType, modifiers);
  9804. for (int i = 0; i < modifiers.Length; ++i) {
  9805. if (optmod.Modifier == modifiers[i]) {
  9806. // strip it
  9807. return t;
  9808. }
  9809. }
  9810. return OptionalModifier.For(optmod.Modifier, t);
  9811. }
  9812. RequiredModifier reqmod = type as RequiredModifier;
  9813. if (reqmod != null) {
  9814. TypeNode t = TypeNode.DeepStripModifiers(reqmod.ModifiedType, modifiers);
  9815. for (int i = 0; i < modifiers.Length; ++i) {
  9816. if (reqmod.Modifier == modifiers[i]) {
  9817. // strip it
  9818. return t;
  9819. }
  9820. }
  9821. return RequiredModifier.For(reqmod.Modifier, t);
  9822. }
  9823. // For arrays and references, strip the inner type and then reconstruct the array or reference
  9824. ArrayType ar = type as ArrayType;
  9825. if (ar != null) {
  9826. TypeNode t = TypeNode.DeepStripModifiers(ar.ElementType, modifiers);
  9827. return t.GetArrayType(1);
  9828. }
  9829. Reference rt = type as Reference;
  9830. if (rt != null) {
  9831. TypeNode t = TypeNode.DeepStripModifiers(rt.ElementType, modifiers);
  9832. return t.GetReferenceType();
  9833. }
  9834. // strip template arguments
  9835. if (type.Template != null && type.TemplateArguments != null && type.TemplateArguments.Count > 0) {
  9836. TypeNodeList strippedArgs = new TypeNodeList(type.TemplateArguments.Count);
  9837. for (int i = 0; i < type.TemplateArguments.Count; i++) {
  9838. strippedArgs.Add(DeepStripModifiers(type.TemplateArguments[i], modifiers));
  9839. }
  9840. return type.Template.GetTemplateInstance(type, strippedArgs);
  9841. }
  9842. return type;
  9843. }
  9844. #endif
  9845. public static bool HasModifier(TypeNode type, TypeNode modifier) {
  9846. // Don't look under pointers or refs.
  9847. TypeModifier tmod = type as TypeModifier;
  9848. if (tmod != null) {
  9849. if (tmod.Modifier == modifier) return true;
  9850. return TypeNode.HasModifier(tmod.ModifiedType, modifier);
  9851. }
  9852. return false;
  9853. }
  9854. public static TypeNode StripModifier(TypeNode type, TypeNode modifier) {
  9855. // Don't strip under pointers or refs. We only strip top-level modifiers
  9856. TypeModifier tmod = type as TypeModifier;
  9857. if (tmod != null){
  9858. TypeNode et = TypeNode.StripModifier(tmod.ModifiedType, modifier);
  9859. //^ assert et != null;
  9860. if (tmod.Modifier == modifier) return et;
  9861. if (et == tmod.ModifiedType) return tmod;
  9862. if (tmod is OptionalModifier) return OptionalModifier.For(tmod.Modifier, et);
  9863. return RequiredModifier.For(tmod.Modifier, et);
  9864. }
  9865. return type;
  9866. }
  9867. /// <summary>
  9868. /// Needed whenever we change the id of an existing member
  9869. /// </summary>
  9870. #if !MinimalReader
  9871. public
  9872. #else
  9873. internal
  9874. #endif
  9875. virtual void ClearMemberTable() {
  9876. lock(this) {
  9877. this.memberTable = null;
  9878. this.memberCount = 0;
  9879. }
  9880. }
  9881. protected virtual void UpdateMemberTable(int range)
  9882. //^ ensures this.memberTable != null;
  9883. {
  9884. MemberList thisMembers = this.Members;
  9885. lock(this){
  9886. if (this.memberTable == null) this.memberTable = new TrivialHashtable(32);
  9887. for (int i = this.memberCount; i < range; i++){
  9888. Member mem = thisMembers[i];
  9889. if (mem == null || mem.Name == null) continue;
  9890. MemberList members = (MemberList)this.memberTable[mem.Name.UniqueIdKey];
  9891. if (members == null) this.memberTable[mem.Name.UniqueIdKey] = members = new MemberList();
  9892. members.Add(mem);
  9893. }
  9894. this.memberCount = range;
  9895. this.constructors = null;
  9896. }
  9897. }
  9898. protected static MemberList WeedOutNonSpecialMethods(MemberList members, MethodFlags mask){
  9899. if (members == null) return null;
  9900. bool membersOK = true;
  9901. for (int i = 0, n = members.Count; i < n; i++){
  9902. Method m = members[i] as Method;
  9903. if (m == null || (m.Flags & mask) == 0){
  9904. membersOK = false; break;
  9905. }
  9906. }
  9907. if (membersOK) return members;
  9908. MemberList newMembers = new MemberList();
  9909. for (int i = 0, n = members.Count; i < n; i++){
  9910. Method m = members[i] as Method;
  9911. if (m == null || (m.Flags & mask) == 0) continue;
  9912. newMembers.Add(m);
  9913. }
  9914. return newMembers;
  9915. }
  9916. #if !NoXml
  9917. public override void WriteDocumentation(XmlTextWriter xwriter){
  9918. base.WriteDocumentation(xwriter);
  9919. MemberList members = this.Members;
  9920. for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++){
  9921. Member mem = members[i];
  9922. if (mem == null) continue;
  9923. mem.WriteDocumentation(xwriter);
  9924. }
  9925. }
  9926. #endif
  9927. #if ExtendedRuntime
  9928. public TypeNode StripOptionalModifiers(out bool nonNull){
  9929. TypeNode t = this;
  9930. nonNull = false;
  9931. for(;;){
  9932. OptionalModifier m = t as OptionalModifier;
  9933. if (m == null)
  9934. break;
  9935. if (m.Modifier == SystemTypes.NonNullType)
  9936. nonNull = true;
  9937. t = m.ModifiedType;
  9938. }
  9939. return t;
  9940. }
  9941. public bool IsObjectReferenceType{
  9942. get{
  9943. bool nonNull;
  9944. TypeNode t = this.StripOptionalModifiers(out nonNull);
  9945. return t is Class || t is Interface || t is ArrayType || t is DelegateNode;
  9946. }
  9947. }
  9948. #endif
  9949. public override string ToString() {
  9950. #if !FxCop
  9951. return this.GetFullUnmangledNameWithTypeParameters();
  9952. #else
  9953. return base.ToString() + ":" + this.GetFullUnmangledNameWithTypeParameters();
  9954. #endif
  9955. }
  9956. #if FxCop
  9957. internal override void GetName(MemberFormat options, StringBuilder name)
  9958. {
  9959. GetName(options.Type, name);
  9960. }
  9961. internal virtual void GetName(TypeFormat options, StringBuilder name)
  9962. {
  9963. if (options.TypeName != TypeNameFormat.None)
  9964. {
  9965. if (this.DeclaringType != null && options.TypeName != TypeNameFormat.InnermostNested)
  9966. {
  9967. this.DeclaringType.GetName(options, name);
  9968. name.Append('+');
  9969. }
  9970. else if (options.TypeName == TypeNameFormat.FullyQualified && this.Namespace.Name.Length > 0)
  9971. {
  9972. name.Append(this.Namespace.Name);
  9973. name.Append('.');
  9974. }
  9975. string shortName = this.Name.Name;
  9976. int mangleChar = shortName.IndexOf(TargetPlatform.GenericTypeNamesMangleChar);
  9977. if (mangleChar != -1)
  9978. shortName = shortName.Substring(0, mangleChar);
  9979. name.Append(shortName);
  9980. }
  9981. TypeNodeList templateParameters = this.TemplateParameters;
  9982. if (this.Template != null) templateParameters = this.TemplateArguments;
  9983. if (templateParameters != null)
  9984. {
  9985. if (options.ShowGenericTypeArity)
  9986. {
  9987. name.Append(TargetPlatform.GenericTypeNamesMangleChar);
  9988. int parametersCount = templateParameters.Count;
  9989. name.Append(Convert.ToString(parametersCount, CultureInfo.InvariantCulture));
  9990. }
  9991. if (options.ShowGenericTypeParameterNames)
  9992. {
  9993. name.Append('<');
  9994. int parametersCount = templateParameters.Count;
  9995. for (int i = 0; i < parametersCount; ++i)
  9996. {
  9997. if (i > 0)
  9998. {
  9999. name.Append(',');
  10000. if (options.InsertSpacesBetweenTypeParameters) name.Append(' ');
  10001. }
  10002. templateParameters[i].GetName(options, name);
  10003. }
  10004. name.Append('>');
  10005. }
  10006. }
  10007. }
  10008. #endif
  10009. }
  10010. #if FxCop
  10011. public class ClassNode : TypeNode{
  10012. #else
  10013. public class Class : TypeNode{
  10014. #endif
  10015. internal readonly static Class DoesNotExist = new Class();
  10016. internal readonly static Class Dummy = new Class();
  10017. internal Class baseClass;
  10018. #if !MinimalReader
  10019. public Class BaseClassExpression;
  10020. public bool IsAbstractSealedContainerForStatics;
  10021. #endif
  10022. #if FxCop
  10023. public ClassNode()
  10024. : base(NodeType.Class){
  10025. }
  10026. public ClassNode(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  10027. : base(NodeType.Class, provideNestedTypes, provideAttributes, provideMembers, handle){
  10028. }
  10029. #else
  10030. public Class()
  10031. : base(NodeType.Class){
  10032. }
  10033. public Class(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  10034. : base(NodeType.Class, provideNestedTypes, provideAttributes, provideMembers, handle){
  10035. }
  10036. #endif
  10037. #if !MinimalReader
  10038. public Class(Module declaringModule, TypeNode declaringType, AttributeList attributes, TypeFlags flags,
  10039. Identifier Namespace, Identifier name, Class baseClass, InterfaceList interfaces, MemberList members)
  10040. : base(declaringModule, declaringType, attributes, flags, Namespace, name, interfaces, members, NodeType.Class){
  10041. this.baseClass = baseClass;
  10042. }
  10043. #endif
  10044. /// <summary>
  10045. /// The class from which this class has been derived. Null if this class is System.Object.
  10046. /// </summary>
  10047. public virtual Class BaseClass{
  10048. get{
  10049. return baseClass;
  10050. }
  10051. set{
  10052. baseClass = value;
  10053. }
  10054. }
  10055. #if !MinimalReader
  10056. public override void GetAbstractMethods(MethodList/*!*/ result) {
  10057. if (!this.IsAbstract) return;
  10058. MethodList candidates = new MethodList();
  10059. if (this.BaseClass != null){
  10060. this.BaseClass.GetAbstractMethods(candidates);
  10061. for (int i = 0, n = candidates.Count; i < n; i++){
  10062. Method meth = candidates[i];
  10063. if (!this.ImplementsMethod(meth, false)) result.Add(meth);
  10064. }
  10065. }
  10066. //Add any abstract methods declared inside this class
  10067. MemberList members = this.Members;
  10068. for (int i = 0, n = members.Count; i < n; i++){
  10069. Method meth = members[i] as Method;
  10070. if (meth == null) continue;
  10071. if (meth.IsAbstract) result.Add(meth);
  10072. }
  10073. //For each interface, get abstract methods and keep those that are not implemented by this class or a base class
  10074. InterfaceList interfaces = this.Interfaces;
  10075. if (interfaces != null)
  10076. for (int i = 0, n = interfaces.Count; i < n; i++){
  10077. Interface iface = interfaces[i];
  10078. if (iface == null) continue;
  10079. MemberList imembers = iface.Members;
  10080. if (imembers == null) continue;
  10081. for (int j = 0, m = imembers.Count; j < m; j++){
  10082. Method meth = imembers[j] as Method;
  10083. if (meth == null) continue;
  10084. if (this.ImplementsExplicitly(meth)) continue;
  10085. if (this.ImplementsMethod(meth,true)) continue;
  10086. if (this.AlreadyInList(result, meth)) continue;
  10087. result.Add(meth);
  10088. }
  10089. }
  10090. }
  10091. protected bool AlreadyInList(MethodList list, Method method){
  10092. if (list == null) return false;
  10093. for (int i = 0, n = list.Count; i < n; i++){
  10094. if (list[i] == method) return true;
  10095. }
  10096. return false;
  10097. }
  10098. #endif
  10099. #if ExtendedRuntime
  10100. public bool IsGuarded{
  10101. get{
  10102. Field f = this.GetField(Identifier.For("SpecSharp::frameGuard"));
  10103. return f != null;
  10104. }
  10105. }
  10106. #endif
  10107. }
  10108. #if !MinimalReader
  10109. public class ClosureClass : Class{
  10110. public ClosureClass(){
  10111. }
  10112. }
  10113. /// <summary>
  10114. /// Does not model a real type, but leverages the symbol table methods of Class. In other words, this is implementation inheritance, not an ISA relationship.
  10115. /// </summary>
  10116. //TODO: use delegation rather than inheritance to achieve this
  10117. public class Scope : Class{
  10118. public Scope(){
  10119. }
  10120. public Scope(Scope outerScope){
  10121. this.OuterScope = outerScope;
  10122. }
  10123. protected Scope outerScope;
  10124. public SourceContext LexicalSourceExtent;
  10125. public Scope OuterScope{
  10126. get{
  10127. if (this.outerScope == null)
  10128. this.outerScope = (Scope)this.baseClass;
  10129. return this.outerScope;
  10130. }
  10131. set{
  10132. this.baseClass = this.outerScope = value;
  10133. }
  10134. }
  10135. public virtual TypeNode GetType(Identifier typeName){
  10136. return this.GetNestedType(typeName);
  10137. }
  10138. }
  10139. public class TypeScope : Scope{
  10140. public TypeNode Type;
  10141. public TypeScope(){}
  10142. public TypeScope(Scope parentScope, TypeNode/*!*/ type) {
  10143. this.baseClass = parentScope;
  10144. this.DeclaringModule = type.DeclaringModule;
  10145. this.Type = type;
  10146. if (type != null && type.PartiallyDefines != null) this.Type = type.PartiallyDefines;
  10147. this.templateParameters = type.TemplateParameters;
  10148. if (type != null)
  10149. this.LexicalSourceExtent = type.SourceContext;
  10150. }
  10151. public override MemberList/*!*/ GetMembersNamed(Identifier name) {
  10152. TypeNode t = this.Type;
  10153. MemberList result = null;
  10154. while (t != null){
  10155. result = t.GetMembersNamed(name);
  10156. if (result.Count > 0) return result;
  10157. t = t.BaseType;
  10158. }
  10159. if (result != null) return result;
  10160. return new MemberList(0);
  10161. }
  10162. public override MemberList Members{
  10163. get{
  10164. return this.Type.Members;
  10165. }
  10166. set{
  10167. base.Members = value;
  10168. }
  10169. }
  10170. }
  10171. public class MethodScope : Scope{
  10172. protected Class closureClass;
  10173. public virtual Class ClosureClass{
  10174. get{
  10175. //if (this.DeclaringMethod == null) return null;
  10176. Class c = this.closureClass;
  10177. if (c == null){
  10178. c = this.closureClass = new ClosureClass();
  10179. c.Name = Identifier.For("closure:"+this.UniqueKey);
  10180. c.BaseClass = CoreSystemTypes.Object;
  10181. Class bclass = this.BaseClass;
  10182. c.DeclaringModule = bclass.DeclaringModule;
  10183. TypeScope tscope = bclass as TypeScope;
  10184. if (tscope != null)
  10185. c.DeclaringType = tscope.Type;
  10186. else{
  10187. MethodScope mscope = bclass as MethodScope;
  10188. if (mscope != null)
  10189. c.DeclaringType = mscope.ClosureClass;
  10190. else
  10191. c.DeclaringType = ((BlockScope)bclass).ClosureClass;
  10192. }
  10193. c.IsGeneric = c.DeclaringType.IsGeneric || this.DeclaringMethod.IsGeneric;
  10194. c.TemplateParameters = this.CopyMethodTemplateParameters(c.DeclaringModule, c.DeclaringType);
  10195. c.Flags = TypeFlags.NestedPrivate|TypeFlags.SpecialName|TypeFlags.Sealed;
  10196. c.Interfaces = new InterfaceList(0);
  10197. if (this.ThisType != null){
  10198. Field f = new Field(c, null, FieldFlags.CompilerControlled | FieldFlags.SpecialName, StandardIds.ThisValue, this.ThisType, null);
  10199. this.ThisField = f;
  10200. c.Members.Add(f);
  10201. }
  10202. }
  10203. return c;
  10204. }
  10205. }
  10206. private TypeNodeList CopyMethodTemplateParameters(Module/*!*/ module, TypeNode/*!*/ type)
  10207. //^ requires this.DeclaringMethod != null;
  10208. {
  10209. TypeNodeList methTemplParams = this.DeclaringMethod.TemplateParameters;
  10210. if (methTemplParams == null || methTemplParams.Count == 0) return null;
  10211. this.tpDup = new TemplateParameterDuplicator(module, type);
  10212. return this.tpDup.VisitTypeParameterList(methTemplParams);
  10213. }
  10214. private TemplateParameterDuplicator tpDup;
  10215. private class TemplateParameterDuplicator : Duplicator{
  10216. public TemplateParameterDuplicator(Module/*!*/ module, TypeNode/*!*/ type)
  10217. : base(module, type){
  10218. }
  10219. public override TypeNode VisitTypeParameter(TypeNode typeParameter){
  10220. if (typeParameter == null) return null;
  10221. TypeNode result = (TypeNode)this.DuplicateFor[typeParameter.UniqueKey];
  10222. if (result != null) return result;
  10223. MethodTypeParameter mtp = typeParameter as MethodTypeParameter;
  10224. if (mtp != null){
  10225. TypeParameter tp = new TypeParameter();
  10226. this.DuplicateFor[typeParameter.UniqueKey] = tp;
  10227. tp.Name = mtp.Name;
  10228. tp.Interfaces = this.VisitInterfaceReferenceList(mtp.Interfaces);
  10229. tp.TypeParameterFlags = mtp.TypeParameterFlags;
  10230. tp.DeclaringModule = mtp.DeclaringModule;
  10231. tp.DeclaringMember = this.TargetType;
  10232. result = tp;
  10233. }else{
  10234. MethodClassParameter mcp = typeParameter as MethodClassParameter;
  10235. if (mcp != null){
  10236. ClassParameter cp = new ClassParameter();
  10237. this.DuplicateFor[typeParameter.UniqueKey] = cp;
  10238. cp.Name = mcp.Name;
  10239. cp.BaseClass = (Class)this.VisitTypeReference(mcp.BaseClass);
  10240. cp.Interfaces = this.VisitInterfaceReferenceList(mcp.Interfaces);
  10241. cp.TypeParameterFlags = mcp.TypeParameterFlags;
  10242. cp.DeclaringModule = mcp.DeclaringModule;
  10243. cp.DeclaringMember = this.TargetType;
  10244. result = cp;
  10245. }
  10246. }
  10247. if (result == null) return typeParameter;
  10248. return result;
  10249. }
  10250. public override TypeNode VisitTypeReference(TypeNode type){
  10251. TypeNode result = base.VisitTypeReference(type);
  10252. if (result == type && (type is MethodClassParameter || type is MethodTypeParameter))
  10253. return this.VisitTypeParameter(type);
  10254. return result;
  10255. }
  10256. }
  10257. public virtual Class ClosureClassTemplateInstance {
  10258. get{
  10259. if (this.closureClassTemplateInstance == null) {
  10260. if (this.DeclaringMethod == null || !this.DeclaringMethod.IsGeneric)
  10261. this.closureClassTemplateInstance = this.ClosureClass;
  10262. else
  10263. this.closureClassTemplateInstance = (Class)this.ClosureClass.GetTemplateInstance(this.DeclaringMethod.DeclaringType, this.DeclaringMethod.TemplateParameters);
  10264. }
  10265. return this.closureClassTemplateInstance;
  10266. }
  10267. }
  10268. Class closureClassTemplateInstance;
  10269. public TypeNode FixTypeReference(TypeNode type) {
  10270. if (this.tpDup == null) return type;
  10271. return this.tpDup.VisitTypeReference(type);
  10272. }
  10273. public virtual Boolean CapturedForClosure{
  10274. get{
  10275. return this.closureClass != null;
  10276. }
  10277. }
  10278. public UsedNamespaceList UsedNamespaces;
  10279. public Field ThisField;
  10280. public TypeNode ThisType;
  10281. public TypeNode ThisTypeInstance;
  10282. public Method DeclaringMethod;
  10283. public MethodScope(){}
  10284. public MethodScope(Class/*!*/ parentScope, UsedNamespaceList usedNamespaces)
  10285. : this(parentScope, usedNamespaces, null){
  10286. }
  10287. public MethodScope(Class/*!*/ parentScope, UsedNamespaceList usedNamespaces, Method method) {
  10288. this.baseClass = parentScope;
  10289. this.UsedNamespaces = usedNamespaces;
  10290. this.DeclaringModule = parentScope.DeclaringModule;
  10291. this.DeclaringMethod = method;
  10292. if (method != null && (method.Flags & MethodFlags.Static) == 0)
  10293. this.ThisType = this.ThisTypeInstance = method.DeclaringType;
  10294. if (method != null)
  10295. this.LexicalSourceExtent = method.SourceContext;
  10296. }
  10297. }
  10298. public class BlockScope : Scope{
  10299. public Block AssociatedBlock;
  10300. public bool MembersArePinned;
  10301. public virtual Class ClosureClass{
  10302. get{
  10303. BlockScope bscope = this.BaseClass as BlockScope;
  10304. if (bscope != null) return bscope.ClosureClass;
  10305. MethodScope mscope = this.BaseClass as MethodScope;
  10306. if (mscope != null) return mscope.ClosureClass;
  10307. return ((TypeScope)this.BaseClass).Type as Class;
  10308. }
  10309. }
  10310. public virtual Boolean CapturedForClosure{
  10311. get{
  10312. BlockScope bscope = this.BaseClass as BlockScope;
  10313. if (bscope != null) return bscope.CapturedForClosure;
  10314. MethodScope mscope = this.BaseClass as MethodScope;
  10315. if (mscope != null) return mscope.CapturedForClosure;
  10316. return false;
  10317. }
  10318. }
  10319. public BlockScope(){
  10320. }
  10321. public BlockScope(Scope/*!*/ parentScope, Block associatedBlock) {
  10322. this.AssociatedBlock = associatedBlock;
  10323. if (associatedBlock != null){
  10324. associatedBlock.HasLocals = true; //TODO: set only if there really are locals
  10325. associatedBlock.Scope = this;
  10326. }
  10327. this.baseClass = parentScope;
  10328. this.DeclaringModule = parentScope.DeclaringModule;
  10329. if (associatedBlock != null)
  10330. this.LexicalSourceExtent = associatedBlock.SourceContext;
  10331. }
  10332. }
  10333. public class AttributeScope : Scope{
  10334. public AttributeNode AssociatedAttribute;
  10335. public AttributeScope(Scope parentScope, AttributeNode associatedAttribute){
  10336. this.AssociatedAttribute = associatedAttribute;
  10337. this.baseClass = parentScope;
  10338. if (associatedAttribute != null)
  10339. this.LexicalSourceExtent = associatedAttribute.SourceContext;
  10340. }
  10341. }
  10342. public class NamespaceScope : Scope{
  10343. public Namespace AssociatedNamespace;
  10344. public Module AssociatedModule;
  10345. public TrivialHashtable AliasedType;
  10346. public TrivialHashtable AliasedNamespace;
  10347. protected TrivialHashtable/*!*/ aliasFor = new TrivialHashtable();
  10348. protected TrivialHashtable/*!*/ typeFor = new TrivialHashtable();
  10349. protected TrivialHashtable/*!*/ namespaceFor = new TrivialHashtable();
  10350. protected TrivialHashtable/*!*/ nestedNamespaceFullName = new TrivialHashtable();
  10351. protected readonly static AliasDefinition/*!*/ noSuchAlias = new AliasDefinition();
  10352. public NamespaceScope(){
  10353. }
  10354. public NamespaceScope(Scope outerScope, Namespace associatedNamespace, Module associatedModule)
  10355. : base(outerScope){
  10356. //^ base;
  10357. this.AssociatedNamespace = associatedNamespace;
  10358. this.AssociatedModule = associatedModule;
  10359. this.DeclaringModule = associatedModule; //TODO: make this go away
  10360. if (associatedNamespace != null)
  10361. this.LexicalSourceExtent = associatedNamespace.SourceContext;
  10362. }
  10363. public virtual AliasDefinition GetAliasFor(Identifier name){
  10364. if (name == null || this.AssociatedNamespace == null || this.AssociatedModule == null || this.aliasFor == null){
  10365. Debug.Assert(false); return null;
  10366. }
  10367. AliasDefinition alias = (AliasDefinition)this.aliasFor[name.UniqueIdKey];
  10368. if (alias == noSuchAlias) return null;
  10369. if (alias != null) return alias;
  10370. //Check if there is an alias with this uri
  10371. Scope scope = this;
  10372. while (scope != null){
  10373. NamespaceScope nsScope = scope as NamespaceScope;
  10374. if (nsScope != null && nsScope.AssociatedNamespace != null){
  10375. AliasDefinitionList aliases = nsScope.AssociatedNamespace.AliasDefinitions;
  10376. if (aliases != null)
  10377. for (int i = 0, n = aliases.Count; i < n; i++){
  10378. AliasDefinition aliasDef = aliases[i];
  10379. if (aliasDef == null || aliasDef.Alias == null) continue;
  10380. if (aliasDef.Alias.UniqueIdKey == name.UniqueIdKey){alias = aliasDef; goto done;}
  10381. }
  10382. }
  10383. scope = scope.OuterScope;
  10384. }
  10385. done:
  10386. if (alias != null)
  10387. this.aliasFor[name.UniqueIdKey] = alias;
  10388. else
  10389. this.aliasFor[name.UniqueIdKey] = noSuchAlias;
  10390. return alias;
  10391. }
  10392. public virtual AliasDefinition GetConflictingAlias(Identifier name){
  10393. if (name == null || this.typeFor == null || this.AssociatedNamespace == null || this.AssociatedModule == null){
  10394. Debug.Assert(false); return null;
  10395. }
  10396. TypeNode type = this.AssociatedModule.GetType(this.AssociatedNamespace.FullNameId, name);
  10397. if (type != null) {
  10398. AliasDefinitionList aliases = this.AssociatedNamespace.AliasDefinitions;
  10399. for (int i = 0, n = aliases == null ? 0 : aliases.Count; i < n; i++){
  10400. //^ assert aliases != null;
  10401. AliasDefinition aliasDef = aliases[i];
  10402. if (aliasDef == null || aliasDef.Alias == null) continue;
  10403. if (aliasDef.Alias.UniqueIdKey == name.UniqueIdKey) return aliasDef;
  10404. }
  10405. }
  10406. Scope scope = this;
  10407. while (scope != null) {
  10408. NamespaceScope outerScope = scope.OuterScope as NamespaceScope;
  10409. if (outerScope != null) return outerScope.GetConflictingAlias(name);
  10410. scope = scope.OuterScope;
  10411. }
  10412. return null;
  10413. }
  10414. public virtual Identifier GetUriFor(Identifier name) {
  10415. AliasDefinition aliasDef = this.GetAliasFor(name);
  10416. if (aliasDef == null) return null;
  10417. return aliasDef.AliasedUri;
  10418. }
  10419. public virtual Identifier GetNamespaceFullNameFor(Identifier name){
  10420. if (name == null || this.AssociatedNamespace == null || this.AssociatedModule == null || this.nestedNamespaceFullName == null){
  10421. Debug.Assert(false); return null;
  10422. }
  10423. Identifier fullName = (Identifier)this.nestedNamespaceFullName[name.UniqueIdKey];
  10424. if (fullName == Identifier.Empty) return null;
  10425. if (fullName != null) return fullName;
  10426. //Check if there is an alias with this namespace
  10427. AliasDefinition aliasDef = this.GetAliasFor(name);
  10428. if (aliasDef != null && aliasDef.AliasedUri == null && aliasDef.AliasedType == null)
  10429. return aliasDef.AliasedExpression as Identifier;
  10430. //Check if module has a type with namespace equal to this namespace + name
  10431. fullName = name;
  10432. if (this.AssociatedNamespace.Name != null && this.AssociatedNamespace.Name.UniqueIdKey != Identifier.Empty.UniqueIdKey)
  10433. fullName = Identifier.For(this.AssociatedNamespace.FullName+"."+name);
  10434. if (this.AssociatedModule.IsValidNamespace(fullName)){
  10435. this.namespaceFor[fullName.UniqueIdKey] = new TrivialHashtable();
  10436. goto returnFullName;
  10437. }
  10438. // If an inner type shadows an outer namespace, don't return the namespace
  10439. if (this.AssociatedModule.IsValidTypeName(this.AssociatedNamespace.Name, name)) { return null; }
  10440. AssemblyReferenceList arefs = this.AssociatedModule.AssemblyReferences;
  10441. for (int i = 0, n = arefs == null ? 0 : arefs.Count; i < n; i++){
  10442. AssemblyReference ar = arefs[i];
  10443. if (ar == null || ar.Assembly == null) continue;
  10444. if (ar.Assembly.IsValidNamespace(fullName)) goto returnFullName;
  10445. // If an inner type shadows an outer namespace, don't return the namespace
  10446. if (ar.Assembly.IsValidTypeName(this.AssociatedNamespace.Name, name)) { return null; }
  10447. }
  10448. ModuleReferenceList mrefs = this.AssociatedModule.ModuleReferences;
  10449. if (mrefs != null)
  10450. for (int i = 0, n = mrefs.Count; i < n; i++){
  10451. ModuleReference mr = mrefs[i];
  10452. if (mr == null || mr.Module == null) continue;
  10453. if (mr.Module.IsValidNamespace(fullName)) goto returnFullName;
  10454. // If an inner type shadows an outer namespace, don't return the namespace
  10455. if (mr.Module.IsValidTypeName(this.AssociatedNamespace.Name, name)) { return null; }
  10456. }
  10457. Scope scope = this.OuterScope;
  10458. while (scope != null && !(scope is NamespaceScope)) scope = scope.OuterScope;
  10459. if (scope != null) return ((NamespaceScope)scope).GetNamespaceFullNameFor(name);
  10460. return null;
  10461. returnFullName:
  10462. this.nestedNamespaceFullName[name.UniqueIdKey] = fullName;
  10463. return fullName;
  10464. }
  10465. /// <summary>
  10466. /// Search this namespace for a type with this name nested in the given namespace. Also considers used name spaces.
  10467. /// If more than one type is found, a list is returned in duplicates.
  10468. /// </summary>
  10469. public virtual TypeNode GetType(Identifier Namespace, Identifier name, out TypeNodeList duplicates){
  10470. duplicates = null;
  10471. if (Namespace == null || name == null || this.AssociatedNamespace == null || this.AssociatedModule == null){
  10472. Debug.Assert(false); return null;
  10473. }
  10474. if (this.namespaceFor == null){
  10475. Debug.Assert(false);
  10476. this.namespaceFor = new TrivialHashtable();
  10477. }
  10478. TrivialHashtable typeFor = (TrivialHashtable)this.namespaceFor[Namespace.UniqueIdKey];
  10479. if (typeFor == null) this.namespaceFor[Namespace.UniqueIdKey] = typeFor = new TrivialHashtable();
  10480. TypeNode result = (TypeNode)typeFor[name.UniqueIdKey];
  10481. if (result == Class.DoesNotExist) return null;
  10482. if (result != null) return result;
  10483. //If the associated module declares a type with the given name in a nested namespace, it wins
  10484. Scope scope = this;
  10485. while (scope != null){
  10486. NamespaceScope nsScope = scope as NamespaceScope;
  10487. if (nsScope != null && nsScope.AssociatedNamespace != null){
  10488. Identifier nestedNamespace = Namespace;
  10489. if (nsScope.AssociatedNamespace.FullNameId != null && nsScope.AssociatedNamespace.FullNameId.UniqueIdKey != Identifier.Empty.UniqueIdKey)
  10490. nestedNamespace = Identifier.For(nsScope.AssociatedNamespace.FullName+"."+Namespace);
  10491. result = this.AssociatedModule.GetType(nestedNamespace, name);
  10492. if (result != null) break;
  10493. }
  10494. scope = scope.OuterScope;
  10495. }
  10496. if (result == null){
  10497. //Now get into situations where there might be duplicates.
  10498. duplicates = new TypeNodeList();
  10499. //Check the used namespaces of this and outer namespace scopes
  10500. TrivialHashtable alreadyUsed = new TrivialHashtable();
  10501. scope = this;
  10502. while (scope != null){
  10503. NamespaceScope nsScope = scope as NamespaceScope;
  10504. if (nsScope != null && nsScope.AssociatedNamespace != null){
  10505. UsedNamespaceList usedNamespaces = nsScope.AssociatedNamespace.UsedNamespaces;
  10506. int n = usedNamespaces == null ? 0 : usedNamespaces.Count;
  10507. if (usedNamespaces != null)
  10508. for (int i = 0; i < n; i++){
  10509. UsedNamespace usedNs = usedNamespaces[i];
  10510. if (usedNs == null || usedNs.Namespace == null) continue;
  10511. int key = usedNs.Namespace.UniqueIdKey;
  10512. if (alreadyUsed[key] != null) continue;
  10513. alreadyUsed[key] = usedNs.Namespace;
  10514. Identifier usedNestedNamespace = Identifier.For(usedNs.Namespace+"."+Namespace);
  10515. result = this.AssociatedModule.GetType(usedNestedNamespace, name);
  10516. if (result != null) duplicates.Add(result);
  10517. }
  10518. }
  10519. scope = scope.OuterScope;
  10520. }
  10521. if (duplicates.Count > 0) result = duplicates[0];
  10522. }
  10523. if (result == null){
  10524. //The associated module does not have a type by this name, so check its referenced modules and assemblies
  10525. int numDups = 0;
  10526. //Check this namespace and outer namespaces
  10527. scope = this;
  10528. while (scope != null && result == null){
  10529. NamespaceScope nsScope = scope as NamespaceScope;
  10530. if (nsScope != null && nsScope.AssociatedNamespace != null){
  10531. Identifier nestedNamespace = Namespace;
  10532. if (nsScope.AssociatedNamespace.FullNameId != null && nsScope.AssociatedNamespace.FullNameId.UniqueIdKey != Identifier.Empty.UniqueIdKey)
  10533. nestedNamespace = Identifier.For(nsScope.AssociatedNamespace.FullName+"."+Namespace);
  10534. nsScope.GetReferencedTypes(nestedNamespace, name, duplicates);
  10535. numDups = duplicates.Count;
  10536. for (int i = numDups-1; i >= 0; i--){
  10537. TypeNode dup = duplicates[i];
  10538. if (dup == null || !dup.IsPublic) numDups--;
  10539. result = dup;
  10540. }
  10541. }
  10542. scope = scope.OuterScope;
  10543. }
  10544. if (numDups == 0){
  10545. if (duplicates.Count > 0) duplicates = new TypeNodeList();
  10546. //Check the used namespaces of this and outer namespace scopes
  10547. TrivialHashtable alreadyUsed = new TrivialHashtable();
  10548. scope = this;
  10549. while (scope != null){
  10550. NamespaceScope nsScope = scope as NamespaceScope;
  10551. if (nsScope != null && nsScope.AssociatedNamespace != null){
  10552. UsedNamespaceList usedNamespaces = this.AssociatedNamespace.UsedNamespaces;
  10553. int n = usedNamespaces == null ? 0 : usedNamespaces.Count;
  10554. if (usedNamespaces != null)
  10555. for (int i = 0; i < n; i++){
  10556. UsedNamespace usedNs = usedNamespaces[i];
  10557. if (usedNs == null) continue;
  10558. int key = usedNs.Namespace.UniqueIdKey;
  10559. if (alreadyUsed[key] != null) continue;
  10560. alreadyUsed[key] = usedNs.Namespace;
  10561. Identifier usedNestedNamespace = Identifier.For(usedNs.Namespace+"."+Namespace);
  10562. this.GetReferencedTypes(usedNestedNamespace, name, duplicates);
  10563. }
  10564. }
  10565. scope = scope.OuterScope;
  10566. }
  10567. numDups = duplicates.Count;
  10568. for (int i = numDups-1; i >= 0; i--){
  10569. TypeNode dup = duplicates[i];
  10570. if (dup == null || !dup.IsPublic) numDups--;
  10571. result = dup;
  10572. }
  10573. }
  10574. if (numDups <= 1) duplicates = null;
  10575. }
  10576. if (result == null)
  10577. typeFor[name.UniqueIdKey] = Class.DoesNotExist;
  10578. else
  10579. typeFor[name.UniqueIdKey] = result;
  10580. return result;
  10581. }
  10582. /// <summary>
  10583. /// Searches this namespace for a type with this name. Also considers aliases and used name spaces, including those of outer namespaces.
  10584. /// If more than one type is found, a list is returned in duplicates. Types defined in the associated
  10585. /// module mask types defined in referenced modules and assemblies. Results are cached and duplicates are returned only when
  10586. /// there is a cache miss.
  10587. /// </summary>
  10588. public virtual TypeNode GetType(Identifier name, out TypeNodeList duplicates){
  10589. return this.GetType(name, out duplicates, false);
  10590. }
  10591. public virtual TypeNode GetType(Identifier name, out TypeNodeList duplicates, bool returnNullIfHiddenByNestedNamespace){
  10592. duplicates = null;
  10593. if (name == null || this.typeFor == null || this.AssociatedNamespace == null || this.AssociatedModule == null){
  10594. Debug.Assert(false); return null;
  10595. }
  10596. AssemblyNode associatedAssembly = this.AssociatedModule as AssemblyNode;
  10597. TypeNode result = (TypeNode)this.typeFor[name.UniqueIdKey];
  10598. if (result == Class.DoesNotExist) return null;
  10599. if (result != null) return result;
  10600. //If the associated module declares a type with the given name in this namespace, it wins
  10601. result = this.AssociatedModule.GetType(this.AssociatedNamespace.FullNameId, name);
  10602. if (result == null && returnNullIfHiddenByNestedNamespace){
  10603. //Do not proceed to outer namespaces or look at aliases. The nested namespace hides these.
  10604. Identifier fullName = name;
  10605. if (this.AssociatedNamespace.FullName != null && this.AssociatedNamespace.Name.UniqueIdKey != Identifier.Empty.UniqueIdKey)
  10606. fullName = Identifier.For(this.AssociatedNamespace.FullName+"."+name);
  10607. if (this.AssociatedModule.IsValidNamespace(fullName))
  10608. result = Class.DoesNotExist;
  10609. }
  10610. if (result == null){
  10611. //If the namespace (or an outer namespace) has an alias definition with this name it wins. (Expected to be mutually exclusive with above.)
  10612. Scope scope = this;
  10613. while (scope != null && result == null){
  10614. NamespaceScope nsScope = scope as NamespaceScope;
  10615. if (nsScope != null && nsScope.AliasedType != null)
  10616. result = (TypeNode)nsScope.AliasedType[name.UniqueIdKey];
  10617. if (result == null && returnNullIfHiddenByNestedNamespace && nsScope != null &&
  10618. nsScope.AliasedNamespace != null && nsScope.AliasedNamespace[name.UniqueIdKey] != null)
  10619. result = Class.DoesNotExist;
  10620. scope = scope.OuterScope;
  10621. }
  10622. }
  10623. if (result == null){
  10624. //Now get into situations where there might be duplicates.
  10625. duplicates = new TypeNodeList();
  10626. //Check the used namespaces of this and outer namespace scopes
  10627. TrivialHashtable alreadyUsed = new TrivialHashtable();
  10628. Scope scope = this;
  10629. while (scope != null) {
  10630. NamespaceScope nsScope = scope as NamespaceScope;
  10631. if (nsScope != null && nsScope.AssociatedNamespace != null && nsScope.AssociatedModule != null) {
  10632. UsedNamespaceList usedNamespaces = nsScope.AssociatedNamespace.UsedNamespaces;
  10633. int n = usedNamespaces == null ? 0 : usedNamespaces.Count;
  10634. if (usedNamespaces != null)
  10635. for (int i = 0; i < n; i++) {
  10636. UsedNamespace usedNs = usedNamespaces[i];
  10637. if (usedNs == null || usedNs.Namespace == null) continue;
  10638. int key = usedNs.Namespace.UniqueIdKey;
  10639. if (alreadyUsed[key] != null) continue;
  10640. alreadyUsed[key] = usedNs.Namespace;
  10641. result = this.AssociatedModule.GetType(usedNs.Namespace, name);
  10642. //^ assert duplicates != null;
  10643. if (result != null) duplicates.Add(result);
  10644. }
  10645. }
  10646. if (returnNullIfHiddenByNestedNamespace) break;
  10647. scope = scope.OuterScope;
  10648. }
  10649. if (duplicates.Count > 0) result = duplicates[0];
  10650. }
  10651. if (result == null)
  10652. //First see if the the current module has a class by this name in the empty namespace
  10653. result = this.AssociatedModule.GetType(Identifier.Empty, name);
  10654. if (result == null){
  10655. //The associated module does not have a type by this name, so check its referenced modules and assemblies
  10656. //First check this namespace
  10657. this.GetReferencedTypes(this.AssociatedNamespace.FullNameId, name, duplicates);
  10658. int numDups = duplicates.Count;
  10659. if (numDups == 1){
  10660. result = duplicates[0];
  10661. if (this.IsNotAccessible(associatedAssembly, result)) { numDups--; result = null; }
  10662. }else{
  10663. for (int i = numDups-1; i >= 0; i--){
  10664. TypeNode dup = duplicates[i];
  10665. if (this.IsNotAccessible(associatedAssembly, dup)) { numDups--; continue; }
  10666. result = dup;
  10667. }
  10668. if (numDups == 0 && duplicates.Count > 0){
  10669. result = duplicates[0];
  10670. numDups = duplicates.Count;
  10671. }
  10672. }
  10673. if (numDups == 0){
  10674. if (duplicates.Count > 0) duplicates = new TypeNodeList();
  10675. //Check the used namespaces of this and outer namespace scopes
  10676. TrivialHashtable alreadyUsed = new TrivialHashtable();
  10677. Scope scope = this;
  10678. while (scope != null) {
  10679. NamespaceScope nsScope = scope as NamespaceScope;
  10680. if (nsScope != null) {
  10681. UsedNamespaceList usedNamespaces = nsScope.AssociatedNamespace.UsedNamespaces;
  10682. int n = usedNamespaces == null ? 0 : usedNamespaces.Count;
  10683. if (usedNamespaces != null)
  10684. for (int i = 0; i < n; i++) {
  10685. UsedNamespace usedNs = usedNamespaces[i];
  10686. if (usedNs == null || usedNs.Namespace == null) continue;
  10687. int key = usedNs.Namespace.UniqueIdKey;
  10688. if (alreadyUsed[key] != null) continue;
  10689. alreadyUsed[key] = usedNs.Namespace;
  10690. this.GetReferencedTypes(usedNs.Namespace, name, duplicates);
  10691. }
  10692. }
  10693. scope = scope.OuterScope;
  10694. if (returnNullIfHiddenByNestedNamespace) break;
  10695. }
  10696. numDups = duplicates.Count;
  10697. for (int i = numDups-1; i >= 0; i--){
  10698. TypeNode dup = duplicates[i];
  10699. if (this.IsNotAccessible(associatedAssembly, dup)) {
  10700. numDups--; continue;
  10701. }
  10702. result = dup;
  10703. }
  10704. }
  10705. if (numDups == 0){
  10706. if (duplicates.Count > 0) duplicates = new TypeNodeList();
  10707. this.GetReferencedTypes(Identifier.Empty, name, duplicates);
  10708. numDups = duplicates.Count;
  10709. for (int i = numDups-1; i >= 0; i--){
  10710. TypeNode dup = duplicates[i];
  10711. if (this.IsNotAccessible(associatedAssembly, dup)) {
  10712. numDups--; continue;
  10713. }
  10714. result = dup;
  10715. }
  10716. }
  10717. if (numDups <= 1) duplicates = null;
  10718. }
  10719. if (result == null)
  10720. this.typeFor[name.UniqueIdKey] = Class.DoesNotExist;
  10721. else
  10722. this.typeFor[name.UniqueIdKey] = result;
  10723. if (result == Class.DoesNotExist) return null;
  10724. if (duplicates != null && duplicates.Count > 1 && this.AssociatedNamespace != null && this.AssociatedNamespace.Name != null && this.AssociatedNamespace.Name.Name != null) {
  10725. result = null;
  10726. for (int i = 0, n = duplicates.Count; i < n; i++) {
  10727. TypeNode t = duplicates[i];
  10728. if (t == null || t.Namespace == null) continue;
  10729. if (this.AssociatedNamespace.Name.Name.StartsWith(t.Namespace.Name)) {
  10730. if (result != null) {
  10731. result = null;
  10732. break;
  10733. }
  10734. result = t;
  10735. }
  10736. }
  10737. if (result != null)
  10738. duplicates = null;
  10739. else
  10740. result = duplicates[0];
  10741. }
  10742. return result;
  10743. }
  10744. private bool IsNotAccessible(AssemblyNode associatedAssembly, TypeNode dup) {
  10745. if (dup == null) return false;
  10746. return !dup.IsPublic && (associatedAssembly == null ||
  10747. !associatedAssembly.MayAccessInternalTypesOf(dup.DeclaringModule as AssemblyNode)) && !this.AssociatedModule.ContainsModule(dup.DeclaringModule);
  10748. }
  10749. /// <summary>
  10750. /// Searches the module and assembly references of the associated module to find types
  10751. /// </summary>
  10752. public virtual void GetReferencedTypes(Identifier Namespace, Identifier name, TypeNodeList types){
  10753. if (Namespace == null || name == null || types == null || this.AssociatedModule == null) {Debug.Assert(false); return;}
  10754. AssemblyReferenceList arefs = this.AssociatedModule.AssemblyReferences;
  10755. for (int i = 0, n = arefs == null ? 0 : arefs.Count; i < n; i++){
  10756. AssemblyReference ar = arefs[i];
  10757. if (ar == null || ar.Assembly == null) continue;
  10758. TypeNode t = ar.Assembly.GetType(Namespace, name);
  10759. if (t == null) continue;
  10760. //TODO: deal with type forwarding
  10761. types.Add(t);
  10762. }
  10763. ModuleReferenceList mrefs = this.AssociatedModule.ModuleReferences;
  10764. if (mrefs != null)
  10765. for (int i = 0, n = mrefs.Count; i < n; i++){
  10766. ModuleReference mr = mrefs[i];
  10767. if (mr == null || mr.Module == null) continue;
  10768. TypeNode t = mr.Module.GetType(Namespace, name);
  10769. if (t == null) continue;
  10770. types.Add(t);
  10771. }
  10772. }
  10773. }
  10774. #endif
  10775. public class DelegateNode : TypeNode{
  10776. internal static readonly DelegateNode/*!*/ Dummy = new DelegateNode();
  10777. protected ParameterList parameters;
  10778. public virtual ParameterList Parameters{
  10779. get{
  10780. ParameterList pList = this.parameters;
  10781. if (pList == null){
  10782. MemberList members = this.Members; //Evaluate for side effect
  10783. if (members != null) members = null;
  10784. lock(this){
  10785. if (this.parameters != null) return this.parameters;
  10786. MemberList invokers = this.GetMembersNamed(StandardIds.Invoke);
  10787. for (int i = 0, n = invokers.Count; i < n; i++){
  10788. Method m = invokers[i] as Method;
  10789. if (m == null) continue;
  10790. this.parameters = pList = m.Parameters;
  10791. this.returnType = m.ReturnType;
  10792. break;
  10793. }
  10794. }
  10795. }
  10796. return pList;
  10797. }
  10798. set{
  10799. this.parameters = value;
  10800. }
  10801. }
  10802. protected TypeNode returnType;
  10803. public virtual TypeNode ReturnType{
  10804. get{
  10805. TypeNode rt = this.returnType;
  10806. if (rt == null){
  10807. ParameterList pars = this.Parameters; //Evaluate for side effect
  10808. if (pars != null) pars = null;
  10809. rt = this.returnType;
  10810. }
  10811. return rt;
  10812. }
  10813. set{
  10814. this.returnType = value;
  10815. }
  10816. }
  10817. #if !MinimalReader
  10818. public TypeNode ReturnTypeExpression;
  10819. #endif
  10820. public DelegateNode()
  10821. : base(NodeType.DelegateNode){
  10822. }
  10823. public DelegateNode(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  10824. : base(NodeType.DelegateNode, provideNestedTypes, provideAttributes, provideMembers, handle){
  10825. }
  10826. #if !MinimalReader
  10827. public DelegateNode(Module declaringModule, TypeNode declaringType, AttributeList attributes, TypeFlags flags,
  10828. Identifier Namespace, Identifier name, TypeNode returnType, ParameterList parameters)
  10829. : base(declaringModule, declaringType, attributes, flags, Namespace, name, null, null, NodeType.DelegateNode){
  10830. this.parameters = parameters;
  10831. this.returnType = returnType;
  10832. }
  10833. private bool membersAlreadyProvided;
  10834. public virtual void ProvideMembers(){
  10835. if (this.membersAlreadyProvided) return;
  10836. this.membersAlreadyProvided = true;
  10837. this.memberCount = 0;
  10838. MemberList members = this.members = new MemberList();
  10839. //ctor
  10840. ParameterList parameters = new ParameterList(2);
  10841. parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.Object, CoreSystemTypes.Object, null, null));
  10842. parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.Method, CoreSystemTypes.IntPtr, null, null));
  10843. InstanceInitializer ctor = new InstanceInitializer(this, null, parameters, null);
  10844. ctor.Flags |= MethodFlags.Public|MethodFlags.HideBySig;
  10845. ctor.CallingConvention = CallingConventionFlags.HasThis;
  10846. ctor.ImplFlags = MethodImplFlags.Runtime;
  10847. members.Add(ctor);
  10848. //Invoke
  10849. Method invoke = new Method(this, null, StandardIds.Invoke, this.Parameters, this.ReturnType, null);
  10850. invoke.Flags = MethodFlags.Public|MethodFlags.HideBySig|MethodFlags.Virtual|MethodFlags.NewSlot;
  10851. invoke.CallingConvention = CallingConventionFlags.HasThis;
  10852. invoke.ImplFlags = MethodImplFlags.Runtime;
  10853. members.Add(invoke);
  10854. // Skip adding async methods if AsyncCallback is a dummy.
  10855. if (SystemTypes.AsyncCallback.ReturnType != null)
  10856. {
  10857. //BeginInvoke
  10858. ParameterList dparams = this.parameters;
  10859. int n = dparams == null ? 0 : dparams.Count;
  10860. parameters = new ParameterList(n + 2);
  10861. for (int i = 0; i < n; i++)
  10862. {
  10863. //^ assert dparams != null;
  10864. Parameter p = dparams[i];
  10865. if (p == null) continue;
  10866. parameters.Add((Parameter)p.Clone());
  10867. }
  10868. parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.callback, SystemTypes.AsyncCallback, null, null));
  10869. parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.Object, CoreSystemTypes.Object, null, null));
  10870. Method beginInvoke = new Method(this, null, StandardIds.BeginInvoke, parameters, SystemTypes.IASyncResult, null);
  10871. beginInvoke.Flags = MethodFlags.Public | MethodFlags.HideBySig | MethodFlags.NewSlot | MethodFlags.Virtual;
  10872. beginInvoke.CallingConvention = CallingConventionFlags.HasThis;
  10873. beginInvoke.ImplFlags = MethodImplFlags.Runtime;
  10874. members.Add(beginInvoke);
  10875. //EndInvoke
  10876. parameters = new ParameterList(1);
  10877. for (int i = 0; i < n; i++)
  10878. {
  10879. Parameter p = dparams[i];
  10880. if (p == null || p.Type == null || !(p.Type is Reference)) continue;
  10881. parameters.Add((Parameter)p.Clone());
  10882. }
  10883. parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.result, SystemTypes.IASyncResult, null, null));
  10884. Method endInvoke = new Method(this, null, StandardIds.EndInvoke, parameters, this.ReturnType, null);
  10885. endInvoke.Flags = MethodFlags.Public | MethodFlags.HideBySig | MethodFlags.NewSlot | MethodFlags.Virtual;
  10886. endInvoke.CallingConvention = CallingConventionFlags.HasThis;
  10887. endInvoke.ImplFlags = MethodImplFlags.Runtime;
  10888. members.Add(endInvoke);
  10889. }
  10890. if (!this.IsGeneric){
  10891. TypeNodeList templPars = this.TemplateParameters;
  10892. for (int i = 0, m = templPars == null ? 0 : templPars.Count; i < m; i++){
  10893. //^ assert templPars != null;
  10894. TypeNode tpar = templPars[i];
  10895. if (tpar == null) continue;
  10896. members.Add(tpar);
  10897. }
  10898. }
  10899. }
  10900. #endif
  10901. }
  10902. #if !MinimalReader
  10903. public class FunctionType : DelegateNode{
  10904. private FunctionType(Identifier name, TypeNode returnType, ParameterList parameters){
  10905. this.Flags = TypeFlags.Public|TypeFlags.Sealed;
  10906. this.Namespace = StandardIds.StructuralTypes;
  10907. this.Name = name;
  10908. this.returnType = returnType;
  10909. this.parameters = parameters;
  10910. }
  10911. public static FunctionType For(TypeNode returnType, ParameterList parameters, TypeNode referringType){
  10912. if (returnType == null || referringType == null) return null;
  10913. Module module = referringType.DeclaringModule;
  10914. if (module == null) return null;
  10915. TypeFlags visibility = returnType.Flags & TypeFlags.VisibilityMask;
  10916. StringBuilder name = new StringBuilder();
  10917. name.Append("Function_");
  10918. name.Append(returnType.Name.ToString());
  10919. int n = parameters == null ? 0 : parameters.Count;
  10920. if (parameters != null)
  10921. for (int i = 0; i < n; i++){
  10922. Parameter p = parameters[i];
  10923. if (p == null || p.Type == null) continue;
  10924. visibility = TypeNode.GetVisibilityIntersection(visibility, p.Type.Flags & TypeFlags.VisibilityMask);
  10925. name.Append('_');
  10926. name.Append(p.Type.Name.ToString());
  10927. }
  10928. FunctionType func = null;
  10929. int count = 0;
  10930. string fNameString = name.ToString();
  10931. Identifier fName = Identifier.For(fNameString);
  10932. TypeNode result = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, fName);
  10933. while (result != null){
  10934. //Mangled name is the same. But mangling is not unique (types are not qualified with assemblies), so check for equality.
  10935. func = result as FunctionType;
  10936. bool goodMatch = func != null && func.ReturnType == returnType;
  10937. if (goodMatch){
  10938. //^ assert func != null;
  10939. ParameterList fpars = func.Parameters;
  10940. int m = fpars == null ? 0 : fpars.Count;
  10941. goodMatch = n == m;
  10942. if (parameters != null && fpars != null)
  10943. for (int i = 0; i < n && goodMatch; i++){
  10944. Parameter p = parameters[i];
  10945. Parameter q = fpars[i];
  10946. goodMatch = p != null && q != null && p.Type == q.Type;
  10947. }
  10948. }
  10949. if (goodMatch) return func;
  10950. //Mangle some more
  10951. fName = Identifier.For(fNameString+(++count).ToString());
  10952. result = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, fName);
  10953. }
  10954. if (parameters != null){
  10955. ParameterList clonedParams = new ParameterList(n);
  10956. for (int i = 0; i < n; i++){
  10957. Parameter p = parameters[i];
  10958. if (p != null) p = (Parameter)p.Clone();
  10959. clonedParams.Add(p);
  10960. }
  10961. parameters = clonedParams;
  10962. }
  10963. func = new FunctionType(fName, returnType, parameters);
  10964. func.DeclaringModule = module;
  10965. switch (visibility){
  10966. case TypeFlags.NestedFamANDAssem:
  10967. case TypeFlags.NestedFamily:
  10968. case TypeFlags.NestedPrivate:
  10969. referringType.Members.Add(func);
  10970. func.DeclaringType = referringType;
  10971. func.Flags &= ~TypeFlags.VisibilityMask;
  10972. func.Flags |= TypeFlags.NestedPrivate;
  10973. break;
  10974. default:
  10975. module.Types.Add(func);
  10976. break;
  10977. }
  10978. module.StructurallyEquivalentType[func.Name.UniqueIdKey] = func;
  10979. func.ProvideMembers();
  10980. return func;
  10981. }
  10982. public override bool IsStructural{
  10983. get{return true;}
  10984. }
  10985. protected TypeNodeList structuralElementTypes;
  10986. public override TypeNodeList StructuralElementTypes{
  10987. get{
  10988. TypeNodeList result = this.structuralElementTypes;
  10989. if (result != null) return result;
  10990. this.structuralElementTypes = result = new TypeNodeList();
  10991. result.Add(this.ReturnType);
  10992. ParameterList pars = this.Parameters;
  10993. for (int i = 0, n = pars == null ? 0 : pars.Count; i < n; i++){
  10994. Parameter par = pars[i];
  10995. if (par == null || par.Type == null) continue;
  10996. result.Add(par.Type);
  10997. }
  10998. return result;
  10999. }
  11000. }
  11001. public override bool IsStructurallyEquivalentTo(TypeNode type){
  11002. if (type == null) return false;
  11003. if (this == type) return true;
  11004. FunctionType t = type as FunctionType;
  11005. if (t == null) return false;
  11006. if (this.Template != null) return base.IsStructurallyEquivalentTo(t);
  11007. if (this.Flags != t.Flags) return false;
  11008. if (this.ReturnType == null || t.ReturnType == null) return false;
  11009. if (this.ReturnType != t.ReturnType && !this.ReturnType.IsStructurallyEquivalentTo(t.ReturnType)) return false;
  11010. if (this.Parameters == null) return t.Parameters == null;
  11011. if (t.Parameters == null) return false;
  11012. int n = this.Parameters.Count; if (n != t.Parameters.Count) return false;
  11013. for (int i = 0; i < n; i++){
  11014. Parameter p1 = this.Parameters[i];
  11015. Parameter p2 = t.Parameters[i];
  11016. if (p1 == null || p2 == null) return false;
  11017. if (p1.Type == null || p2.Type == null) return false;
  11018. if (p1.Type != p2.Type && !p1.Type.IsStructurallyEquivalentTo(p2.Type)) return false;
  11019. }
  11020. return true;
  11021. }
  11022. }
  11023. #endif
  11024. public class EnumNode : TypeNode{
  11025. internal readonly static EnumNode/*!*/ Dummy = new EnumNode();
  11026. public EnumNode()
  11027. : base(NodeType.EnumNode){
  11028. this.typeCode = ElementType.ValueType;
  11029. this.Flags |= TypeFlags.Sealed;
  11030. }
  11031. public EnumNode(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  11032. : base(NodeType.EnumNode, provideNestedTypes, provideAttributes, provideMembers, handle){
  11033. this.typeCode = ElementType.ValueType;
  11034. this.Flags |= TypeFlags.Sealed;
  11035. }
  11036. #if !MinimalReader
  11037. public EnumNode(Module declaringModule, TypeNode declaringType, AttributeList attributes, TypeFlags typeAttributes,
  11038. Identifier Namespace, Identifier name, InterfaceList interfaces, MemberList members)
  11039. : base(declaringModule, declaringType, attributes, typeAttributes, Namespace, name, interfaces, members, NodeType.EnumNode){
  11040. this.typeCode = ElementType.ValueType;
  11041. this.Flags |= TypeFlags.Sealed;
  11042. }
  11043. #endif
  11044. public override bool IsUnmanaged{
  11045. get{
  11046. return true;
  11047. }
  11048. }
  11049. protected internal TypeNode underlyingType;
  11050. /// <summary>
  11051. /// The underlying integer type used to store values of this enumeration.
  11052. /// </summary>
  11053. public virtual TypeNode UnderlyingType{
  11054. get{
  11055. if (this.underlyingType == null){
  11056. if (this.template is EnumNode)
  11057. return this.underlyingType = ((EnumNode)this.template).UnderlyingType;
  11058. this.underlyingType = CoreSystemTypes.Int32;
  11059. MemberList members = this.Members;
  11060. for (int i = 0, n = members.Count; i < n; i++){
  11061. Member mem = members[i];
  11062. Field f = mem as Field;
  11063. if (f != null && (f.Flags & FieldFlags.Static) == 0)
  11064. return this.underlyingType = f.Type;
  11065. }
  11066. }
  11067. return this.underlyingType;
  11068. }
  11069. set{
  11070. this.underlyingType = value;
  11071. MemberList members = this.Members;
  11072. for (int i = 0, n = members.Count; i < n; i++){
  11073. Member mem = members[i];
  11074. Field f = mem as Field;
  11075. if (f != null && (f.Flags & FieldFlags.Static) == 0){
  11076. f.Type = value;
  11077. return;
  11078. }
  11079. }
  11080. this.Members.Add(new Field(this, null, FieldFlags.Public|FieldFlags.SpecialName|FieldFlags.RTSpecialName, StandardIds.Value__, value, null));
  11081. }
  11082. }
  11083. #if ExtendedRuntime
  11084. public override bool IsPointerFree
  11085. {
  11086. get
  11087. {
  11088. return true;
  11089. }
  11090. }
  11091. #endif
  11092. #if !MinimalReader
  11093. public TypeNode UnderlyingTypeExpression;
  11094. #endif
  11095. }
  11096. #if FxCop
  11097. public class InterfaceNode : TypeNode{
  11098. #else
  11099. public class Interface : TypeNode{
  11100. #endif
  11101. protected TrivialHashtable jointMemberTable;
  11102. protected MemberList jointDefaultMembers;
  11103. internal static readonly Interface/*!*/ Dummy = new Interface();
  11104. #if FxCop
  11105. public InterfaceNode()
  11106. : base(NodeType.Interface){
  11107. this.Flags = TypeFlags.Interface|TypeFlags.Abstract;
  11108. }
  11109. public InterfaceNode(InterfaceList baseInterfaces)
  11110. : base(NodeType.Interface){
  11111. this.Interfaces = baseInterfaces;
  11112. this.Flags = TypeFlags.Interface|TypeFlags.Abstract;
  11113. }
  11114. public InterfaceNode(InterfaceList baseInterfaces, NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  11115. : base(NodeType.Interface, provideNestedTypes, provideAttributes, provideMembers, handle){
  11116. this.Interfaces = baseInterfaces;
  11117. }
  11118. #else
  11119. public Interface()
  11120. : base(NodeType.Interface){
  11121. this.Flags = TypeFlags.Interface|TypeFlags.Abstract;
  11122. }
  11123. public Interface(InterfaceList baseInterfaces)
  11124. : base(NodeType.Interface){
  11125. this.Interfaces = baseInterfaces;
  11126. this.Flags = TypeFlags.Interface|TypeFlags.Abstract;
  11127. }
  11128. public Interface(InterfaceList baseInterfaces, NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  11129. : base(NodeType.Interface, provideNestedTypes, provideAttributes, provideMembers, handle){
  11130. this.Interfaces = baseInterfaces;
  11131. }
  11132. #endif
  11133. #if !MinimalReader
  11134. public Interface(Module declaringModule, TypeNode declaringType, AttributeList attributes, TypeFlags flags,
  11135. Identifier Namespace, Identifier name, InterfaceList baseInterfaces, MemberList members)
  11136. : base(declaringModule, declaringType, attributes, flags, Namespace, name, baseInterfaces, members, NodeType.Interface){
  11137. this.Flags |= TypeFlags.Interface|TypeFlags.Abstract;
  11138. }
  11139. public override void GetAbstractMethods(MethodList/*!*/ result) {
  11140. MemberList members = this.Members;
  11141. if (members == null) return;
  11142. for (int i = 0, n = members.Count; i < n; i++){
  11143. Method m = members[i] as Method;
  11144. if (m != null) result.Add(m);
  11145. }
  11146. }
  11147. public virtual MemberList GetAllDefaultMembers() {
  11148. if (this.jointDefaultMembers == null) {
  11149. this.jointDefaultMembers = new MemberList();
  11150. MemberList defs = this.DefaultMembers;
  11151. for (int i = 0, n = defs == null ? 0 : defs.Count; i < n; i++)
  11152. this.jointDefaultMembers.Add(defs[i]);
  11153. InterfaceList interfaces = this.Interfaces;
  11154. if (interfaces != null)
  11155. for (int j = 0, m = interfaces.Count; j < m; j++) {
  11156. Interface iface = interfaces[j];
  11157. if (iface == null) continue;
  11158. defs = iface.GetAllDefaultMembers();
  11159. if (defs == null) continue;
  11160. for (int i = 0, n = defs.Count; i < n; i++)
  11161. this.jointDefaultMembers.Add(defs[i]);
  11162. }
  11163. }
  11164. return this.jointDefaultMembers;
  11165. }
  11166. public virtual MemberList GetAllMembersNamed(Identifier/*!*/ name) {
  11167. lock (this){
  11168. TrivialHashtable memberTable = this.jointMemberTable;
  11169. if (memberTable == null) this.jointMemberTable = memberTable = new TrivialHashtable();
  11170. MemberList result = (MemberList)memberTable[name.UniqueIdKey];
  11171. if (result != null) return result;
  11172. memberTable[name.UniqueIdKey] = result = new MemberList();
  11173. MemberList members = this.GetMembersNamed(name);
  11174. for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++)
  11175. result.Add(members[i]);
  11176. InterfaceList interfaces = this.Interfaces;
  11177. for (int j = 0, m = interfaces == null ? 0 : interfaces.Count; j < m; j++){
  11178. Interface iface = interfaces[j];
  11179. if (iface == null) continue;
  11180. members = iface.GetAllMembersNamed(name);
  11181. if (members != null)
  11182. for (int i = 0, n = members.Count; i < n; i++)
  11183. result.Add(members[i]);
  11184. }
  11185. members = CoreSystemTypes.Object.GetMembersNamed(name);
  11186. for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++)
  11187. result.Add(members[i]);
  11188. return result;
  11189. }
  11190. }
  11191. #endif
  11192. }
  11193. public class Struct : TypeNode{
  11194. internal static readonly Struct/*!*/ Dummy = new Struct();
  11195. public Struct()
  11196. : base(NodeType.Struct){
  11197. this.typeCode = ElementType.ValueType;
  11198. this.Flags = TypeFlags.Sealed;
  11199. }
  11200. public Struct(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  11201. : base(NodeType.Struct, provideNestedTypes, provideAttributes, provideMembers, handle){
  11202. this.typeCode = ElementType.ValueType;
  11203. }
  11204. #if !MinimalReader
  11205. public Struct(Module declaringModule, TypeNode declaringType, AttributeList attributes, TypeFlags flags,
  11206. Identifier Namespace, Identifier name, InterfaceList interfaces, MemberList members)
  11207. : base(declaringModule, declaringType, attributes, flags, Namespace, name, interfaces, members, NodeType.Struct){
  11208. this.Interfaces = interfaces;
  11209. this.typeCode = ElementType.ValueType;
  11210. this.Flags |= TypeFlags.Sealed;
  11211. }
  11212. protected bool cachedUnmanaged;
  11213. protected bool cachedUnmanagedIsValid;
  11214. /// <summary>True if the type is a value type containing only fields of unmanaged types.</summary>
  11215. public override bool IsUnmanaged{
  11216. get{
  11217. if (this.cachedUnmanagedIsValid) return this.cachedUnmanaged;
  11218. this.cachedUnmanagedIsValid = true; //protect against cycles
  11219. this.cachedUnmanaged = true; //Self references should not influence the answer
  11220. if (this.IsPrimitive) return this.cachedUnmanaged = true;
  11221. MemberList members = this.Members;
  11222. bool isUnmanaged = true;
  11223. for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++){
  11224. Field f = members[i] as Field;
  11225. if (f == null || f.Type == null || f.IsStatic) continue;
  11226. if (!f.Type.IsUnmanaged){isUnmanaged = false; break;}
  11227. }
  11228. #if ExtendedRuntime
  11229. this.cachedUnmanaged = isUnmanaged || IsPointerFree;
  11230. #else
  11231. this.cachedUnmanaged = isUnmanaged;
  11232. #endif
  11233. return this.cachedUnmanaged;
  11234. }
  11235. }
  11236. #endif
  11237. #if ExtendedRuntime
  11238. protected bool cachedPointerFree;
  11239. protected bool cachedPointerFreeIsValid;
  11240. /// <summary>True if the type is a value type containing no managed or unmanaged pointers.</summary>
  11241. public override bool IsPointerFree
  11242. {
  11243. get
  11244. {
  11245. if (this.cachedPointerFreeIsValid) return this.cachedPointerFree;
  11246. // Note: not threadsafe
  11247. this.cachedPointerFreeIsValid = true; //protect against cycles
  11248. this.cachedPointerFree = true; //Self references should not influence the answer
  11249. if (this.IsPrimitive) return this.cachedPointerFree = true;
  11250. MemberList members = this.Members;
  11251. bool isPointerFree = true;
  11252. for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++)
  11253. {
  11254. Field f = members[i] as Field;
  11255. if (f == null || f.Type == null || f.IsStatic) continue;
  11256. if (!f.Type.IsPointerFree) { isPointerFree = false; break; }
  11257. }
  11258. return this.cachedPointerFree = isPointerFree;
  11259. }
  11260. }
  11261. #endif
  11262. }
  11263. public interface ITypeParameter{
  11264. Member DeclaringMember{get;set;}
  11265. /// <summary>
  11266. /// Zero based index into a parameter list containing this parameter.
  11267. /// </summary>
  11268. int ParameterListIndex{get;set;}
  11269. TypeParameterFlags TypeParameterFlags{get;set;}
  11270. bool IsUnmanaged { get; }
  11271. #if ExtendedRuntime
  11272. bool IsPointerFree { get; }
  11273. #endif
  11274. #if !MinimalReader
  11275. Identifier Name { get; }
  11276. Module DeclaringModule { get; }
  11277. TypeNode DeclaringType { get; }
  11278. SourceContext SourceContext { get; }
  11279. int UniqueKey { get; }
  11280. TypeFlags Flags { get; }
  11281. #endif
  11282. }
  11283. public class TypeParameter : Interface, ITypeParameter{
  11284. public TypeParameter()
  11285. : base(){
  11286. this.NodeType = NodeType.TypeParameter;
  11287. this.Flags = TypeFlags.Interface|TypeFlags.NestedPublic|TypeFlags.Abstract;
  11288. this.Namespace = StandardIds.TypeParameter;
  11289. }
  11290. public TypeParameter(InterfaceList baseInterfaces, NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  11291. : base(baseInterfaces, provideNestedTypes, provideAttributes, provideMembers, handle){
  11292. this.NodeType = NodeType.TypeParameter;
  11293. this.Flags = TypeFlags.Interface|TypeFlags.NestedPublic|TypeFlags.Abstract;
  11294. this.Namespace = StandardIds.TypeParameter;
  11295. }
  11296. public Member DeclaringMember{
  11297. get{return this.declaringMember;}
  11298. set{this.declaringMember = value;}
  11299. }
  11300. private Member declaringMember;
  11301. #if !NoReflection && WHIDBEY
  11302. public override Type GetRuntimeType() {
  11303. TypeNode t = this.DeclaringMember as TypeNode;
  11304. if (t == null) return null;
  11305. Type rt = t.GetRuntimeType();
  11306. if (rt == null) return null;
  11307. System.Type[] typeParameters = rt.GetGenericArguments();
  11308. if (this.ParameterListIndex >= typeParameters.Length) return null;
  11309. return typeParameters[this.ParameterListIndex];
  11310. }
  11311. #endif
  11312. /// <summary>
  11313. /// Zero based index into a parameter list containing this parameter.
  11314. /// </summary>
  11315. public int ParameterListIndex{
  11316. get{return this.parameterListIndex;}
  11317. set{this.parameterListIndex = value;}
  11318. }
  11319. private int parameterListIndex;
  11320. #if ExtendedRuntime
  11321. private bool typeParameterFlagsIsValid = false;
  11322. #endif
  11323. public TypeParameterFlags TypeParameterFlags{
  11324. get{
  11325. #if ExtendedRuntime
  11326. if (!typeParameterFlagsIsValid) {
  11327. // check if we have the corresponding attribute
  11328. for (int i=0; i < (this.Attributes == null?0:this.Attributes.Count); i++) {
  11329. if (this.Attributes[i].Type == SystemTypes.TemplateParameterFlagsAttribute) {
  11330. Literal lit = this.Attributes[i].Expressions[0] as Literal;
  11331. if (lit != null && lit.Value is int) {
  11332. this.typeParameterFlags = (TypeParameterFlags)((int)lit.Value);
  11333. }
  11334. break;
  11335. }
  11336. }
  11337. this.typeParameterFlagsIsValid = true;
  11338. }
  11339. #endif
  11340. return this.typeParameterFlags;
  11341. }
  11342. set{
  11343. this.typeParameterFlags = value;
  11344. #if ExtendedRuntime
  11345. this.typeParameterFlagsIsValid = true;
  11346. #endif
  11347. }
  11348. }
  11349. private TypeParameterFlags typeParameterFlags;
  11350. public override bool IsStructural{
  11351. get{return true;}
  11352. }
  11353. /// <summary>True if the type serves as a parameter to a type template.</summary>
  11354. public override bool IsTemplateParameter{
  11355. get{
  11356. return true;
  11357. }
  11358. }
  11359. public override bool IsValueType {
  11360. get {
  11361. return ((this.TypeParameterFlags & TypeParameterFlags.ValueTypeConstraint) == TypeParameterFlags.ValueTypeConstraint);
  11362. }
  11363. }
  11364. #if ExtendedRuntime
  11365. public override bool IsReferenceType {
  11366. get {
  11367. return ((this.TypeParameterFlags & TypeParameterFlags.ReferenceTypeConstraint) == TypeParameterFlags.ReferenceTypeConstraint);
  11368. }
  11369. }
  11370. private bool isUnmanagedIsValid = false;
  11371. private bool isUnmanaged = false;
  11372. public override bool IsUnmanaged{
  11373. get{
  11374. if (!isUnmanagedIsValid && SystemTypes.UnmanagedStructTemplateParameterAttribute != null){
  11375. // check if we have the corresponding attribute
  11376. for (int i=0; i < (this.Attributes == null?0:this.Attributes.Count); i++){
  11377. AttributeNode attr = this.Attributes[i];
  11378. if (attr == null) continue;
  11379. if (attr.Type == SystemTypes.UnmanagedStructTemplateParameterAttribute){
  11380. isUnmanaged = true;
  11381. break;
  11382. }
  11383. #if ExtendedRuntime
  11384. if (!isUnmanaged) { isUnmanaged = IsPointerFree; }
  11385. #endif
  11386. }
  11387. isUnmanagedIsValid = true;
  11388. }
  11389. return isUnmanaged;
  11390. }
  11391. }
  11392. public void SetIsUnmanaged(){
  11393. this.isUnmanaged = true;
  11394. this.isUnmanagedIsValid = true;
  11395. }
  11396. private bool isPointerFreeIsValid = false;
  11397. private bool isPointerFree = false;
  11398. public override bool IsPointerFree
  11399. {
  11400. get
  11401. {
  11402. if (!isPointerFreeIsValid && SystemTypes.PointerFreeStructTemplateParameterAttribute != null)
  11403. {
  11404. // check if we have the corresponding attribute
  11405. for (int i = 0; i < (this.Attributes == null ? 0 : this.Attributes.Count); i++)
  11406. {
  11407. AttributeNode attr = this.Attributes[i];
  11408. if (attr == null) continue;
  11409. if (attr.Type == SystemTypes.PointerFreeStructTemplateParameterAttribute)
  11410. {
  11411. isPointerFree = true;
  11412. break;
  11413. }
  11414. }
  11415. isPointerFreeIsValid = true;
  11416. }
  11417. return isPointerFree;
  11418. }
  11419. }
  11420. public void SetIsPointerFree()
  11421. {
  11422. this.isPointerFree = true;
  11423. this.isPointerFreeIsValid = true;
  11424. // implies unmanaged
  11425. SetIsUnmanaged();
  11426. }
  11427. #endif
  11428. #if !NoXml
  11429. public override XmlNode Documentation{
  11430. get{
  11431. if (this.documentation == null && this.declaringMember != null && this.Name != null){
  11432. XmlNode parentDoc = this.declaringMember.Documentation;
  11433. if (parentDoc != null && parentDoc.HasChildNodes){
  11434. string myName = this.Name.Name;
  11435. foreach (XmlNode child in parentDoc.ChildNodes){
  11436. if (child.Name == "typeparam" && child.Attributes != null){
  11437. foreach (XmlAttribute attr in child.Attributes){
  11438. if (attr != null && attr.Name == "name" && attr.Value == myName)
  11439. return this.documentation = child;
  11440. }
  11441. }
  11442. }
  11443. }
  11444. }
  11445. return this.documentation;
  11446. }
  11447. set{
  11448. this.documentation = value;
  11449. }
  11450. }
  11451. public override string HelpText{
  11452. get{
  11453. if (this.helpText == null){
  11454. XmlNode doc = this.Documentation;
  11455. if (doc != null) this.helpText = doc.InnerText;
  11456. }
  11457. return this.helpText;
  11458. }
  11459. set{
  11460. this.helpText = value;
  11461. }
  11462. }
  11463. #endif
  11464. protected internal TypeNodeList structuralElementTypes;
  11465. public override TypeNodeList StructuralElementTypes{
  11466. get{
  11467. TypeNodeList result = this.structuralElementTypes;
  11468. if (result != null) return result;
  11469. this.structuralElementTypes = result = new TypeNodeList();
  11470. if (this.BaseType != null) result.Add(this.BaseType);
  11471. InterfaceList interfaces = this.Interfaces;
  11472. for (int i = 0, n = interfaces == null ? 0 : interfaces.Count; i < n; i++){
  11473. Interface iface = interfaces[i];
  11474. if (iface == null) continue;
  11475. result.Add(iface);
  11476. }
  11477. return result;
  11478. }
  11479. }
  11480. #if !NoXml
  11481. internal override void AppendDocumentIdMangledName(StringBuilder/*!*/ sb, TypeNodeList methodTypeParameters, TypeNodeList typeParameters) {
  11482. if (TargetPlatform.GenericTypeNamesMangleChar != 0) {
  11483. int n = methodTypeParameters == null ? 0 : methodTypeParameters.Count;
  11484. for (int i = 0; i < n; i++){
  11485. //^ assert methodTypeParameters != null;
  11486. TypeNode mpar = methodTypeParameters[i];
  11487. if (mpar != this) continue;
  11488. sb.Append(TargetPlatform.GenericTypeNamesMangleChar);
  11489. sb.Append(TargetPlatform.GenericTypeNamesMangleChar);
  11490. sb.Append(i);
  11491. return;
  11492. }
  11493. n = typeParameters == null ? 0 : typeParameters.Count;
  11494. for (int i = 0; i < n; i++){
  11495. TypeNode tpar = typeParameters[i];
  11496. if (tpar != this) continue;
  11497. sb.Append(TargetPlatform.GenericTypeNamesMangleChar);
  11498. sb.Append(i);
  11499. return;
  11500. }
  11501. sb.Append("not found:");
  11502. }
  11503. sb.Append(this.FullName);
  11504. }
  11505. #endif
  11506. public override string GetFullUnmangledNameWithoutTypeParameters(){
  11507. return this.GetUnmangledNameWithoutTypeParameters();
  11508. }
  11509. public override string GetFullUnmangledNameWithTypeParameters(){
  11510. return this.GetUnmangledNameWithTypeParameters();
  11511. }
  11512. public override bool IsStructurallyEquivalentTo(TypeNode type){
  11513. if (null == (object)type) return false;
  11514. if (this == type) return true;
  11515. ITypeParameter itype = type as ITypeParameter;
  11516. if (null == (object)itype) return false;
  11517. if (this.Name != null && type.Name != null && this.Name.UniqueIdKey != type.Name.UniqueIdKey) {
  11518. if (this.DeclaringMember == itype.DeclaringMember) return false;
  11519. }
  11520. TypeNode bType = this.BaseType;
  11521. TypeNode tbType = type.BaseType;
  11522. if (null == (object)bType) bType = CoreSystemTypes.Object;
  11523. if (null == (object)tbType) tbType = CoreSystemTypes.Object;
  11524. if (bType != tbType /*&& !bType.IsStructurallyEquivalentTo(tbType)*/) return false;
  11525. if (this.Interfaces == null) return type.Interfaces == null || type.Interfaces.Count == 0;
  11526. if (type.Interfaces == null) return this.Interfaces.Count == 0;
  11527. int n = this.Interfaces.Count; if (n != type.Interfaces.Count) return false;
  11528. for (int i = 0; i < n; i++){
  11529. Interface i1 = this.Interfaces[i];
  11530. Interface i2 = type.Interfaces[i];
  11531. if (null == (object)i1 || null == (object)i2) return false;
  11532. if (i1 != i2 /*&& !i1.IsStructurallyEquivalentTo(i2)*/) return false;
  11533. }
  11534. return true;
  11535. }
  11536. #if !MinimalReader
  11537. Module ITypeParameter.DeclaringModule { get { return this.DeclaringModule; } }
  11538. TypeFlags ITypeParameter.Flags { get { return this.Flags; } }
  11539. SourceContext ITypeParameter.SourceContext { get { return this.SourceContext; } }
  11540. #endif
  11541. #if FxCop
  11542. internal override void GetName(TypeFormat options, StringBuilder name)
  11543. {
  11544. if (options.TypeName == TypeNameFormat.FullyQualified)
  11545. {
  11546. TypeFormat typeFormat = options.Clone();
  11547. typeFormat.TypeName = TypeNameFormat.Short;
  11548. base.GetName(typeFormat, name);
  11549. return;
  11550. }
  11551. base.GetName(options, name);
  11552. }
  11553. #endif
  11554. }
  11555. public class MethodTypeParameter : TypeParameter{
  11556. public MethodTypeParameter()
  11557. : base(){
  11558. this.NodeType = NodeType.TypeParameter;
  11559. this.Flags = TypeFlags.Interface|TypeFlags.NestedPublic|TypeFlags.Abstract;
  11560. this.Namespace = StandardIds.TypeParameter;
  11561. }
  11562. #if !MinimalReader
  11563. public MethodTypeParameter(InterfaceList baseInterfaces, NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  11564. : base(baseInterfaces, provideNestedTypes, provideAttributes, provideMembers, handle) {
  11565. this.NodeType = NodeType.TypeParameter;
  11566. this.Flags = TypeFlags.Interface|TypeFlags.NestedPublic|TypeFlags.Abstract;
  11567. this.Namespace = StandardIds.TypeParameter;
  11568. }
  11569. #endif
  11570. #if !NoReflection
  11571. #if WHIDBEY
  11572. public override Type GetRuntimeType() {
  11573. Method m = this.DeclaringMember as Method;
  11574. if (m == null) return null;
  11575. System.Reflection.MethodInfo mi = m.GetMethodInfo();
  11576. if (mi == null) return null;
  11577. System.Type[] typeParameters = mi.GetGenericArguments();
  11578. if (this.ParameterListIndex >= typeParameters.Length) return null;
  11579. return typeParameters[this.ParameterListIndex];
  11580. }
  11581. #endif
  11582. #endif
  11583. public override bool IsStructurallyEquivalentTo(TypeNode type) {
  11584. if (object.ReferenceEquals(this, type)) return true;
  11585. ITypeParameter tp = type as ITypeParameter;
  11586. if (tp == null) return false;
  11587. if (this.ParameterListIndex == tp.ParameterListIndex && this.DeclaringMember == tp.DeclaringMember) return true;
  11588. return base.IsStructurallyEquivalentTo(type as MethodTypeParameter);
  11589. }
  11590. }
  11591. public class ClassParameter : Class, ITypeParameter{
  11592. protected TrivialHashtable jointMemberTable;
  11593. public ClassParameter()
  11594. : base(){
  11595. this.NodeType = NodeType.ClassParameter;
  11596. this.baseClass = CoreSystemTypes.Object;
  11597. this.Flags = TypeFlags.NestedPublic|TypeFlags.Abstract;
  11598. this.Namespace = StandardIds.TypeParameter;
  11599. }
  11600. public ClassParameter(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  11601. : base(provideNestedTypes, provideAttributes, provideMembers, handle){
  11602. this.NodeType = NodeType.ClassParameter;
  11603. this.baseClass = CoreSystemTypes.Object;
  11604. this.Flags = TypeFlags.NestedPrivate|TypeFlags.Abstract|TypeFlags.SpecialName;
  11605. this.Namespace = StandardIds.TypeParameter;
  11606. }
  11607. public Member DeclaringMember{
  11608. get{return this.declaringMember;}
  11609. set{this.declaringMember = value;}
  11610. }
  11611. private Member declaringMember;
  11612. #if !MinimalReader
  11613. public virtual MemberList GetAllMembersNamed(Identifier/*!*/ name) {
  11614. lock (this) {
  11615. TrivialHashtable memberTable = this.jointMemberTable;
  11616. if (memberTable == null) this.jointMemberTable = memberTable = new TrivialHashtable();
  11617. MemberList result = (MemberList)memberTable[name.UniqueIdKey];
  11618. if (result != null) return result;
  11619. memberTable[name.UniqueIdKey] = result = new MemberList();
  11620. TypeNode t = this;
  11621. while (t != null) {
  11622. MemberList members = t.GetMembersNamed(name);
  11623. if (members != null)
  11624. for (int i = 0, n = members.Count; i < n; i++)
  11625. result.Add(members[i]);
  11626. t = t.BaseType;
  11627. }
  11628. InterfaceList interfaces = this.Interfaces;
  11629. if (interfaces != null)
  11630. for (int j = 0, m = interfaces.Count; j < m; j++) {
  11631. Interface iface = interfaces[j];
  11632. if (iface == null) continue;
  11633. members = iface.GetAllMembersNamed(name);
  11634. if (members != null)
  11635. for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++)
  11636. result.Add(members[i]);
  11637. }
  11638. members = CoreSystemTypes.Object.GetMembersNamed(name);
  11639. if (members != null)
  11640. for (int i = 0, n = members.Count; i < n; i++)
  11641. result.Add(members[i]);
  11642. return result;
  11643. }
  11644. }
  11645. #endif
  11646. #if !NoReflection && WHIDBEY
  11647. public override Type GetRuntimeType() {
  11648. TypeNode t = this.DeclaringMember as TypeNode;
  11649. if (t == null) return null;
  11650. Type rt = t.GetRuntimeType();
  11651. if (rt == null) return null;
  11652. System.Type[] typeParameters = rt.GetGenericArguments();
  11653. if (this.ParameterListIndex >= typeParameters.Length) return null;
  11654. return typeParameters[this.ParameterListIndex];
  11655. }
  11656. #endif
  11657. /// <summary>
  11658. /// Zero based index into a parameter list containing this parameter.
  11659. /// </summary>
  11660. public int ParameterListIndex{
  11661. get{return this.parameterListIndex;}
  11662. set{this.parameterListIndex = value;}
  11663. }
  11664. private int parameterListIndex;
  11665. public TypeParameterFlags TypeParameterFlags{
  11666. get{return this.typeParameterFlags;}
  11667. set{this.typeParameterFlags = value;}
  11668. }
  11669. private TypeParameterFlags typeParameterFlags;
  11670. public override bool IsValueType {
  11671. get {
  11672. return ((this.typeParameterFlags & TypeParameterFlags.ValueTypeConstraint) == TypeParameterFlags.ValueTypeConstraint);
  11673. }
  11674. }
  11675. public override bool IsStructural {
  11676. get{return true;}
  11677. }
  11678. /// <summary>True if the type serves as a parameter to a type template.</summary>
  11679. public override bool IsTemplateParameter{
  11680. get{
  11681. return true;
  11682. }
  11683. }
  11684. #if ExtendedRuntime
  11685. public override bool IsReferenceType {
  11686. get {
  11687. return ((this.TypeParameterFlags & TypeParameterFlags.ReferenceTypeConstraint) == TypeParameterFlags.ReferenceTypeConstraint)
  11688. || (this.baseClass != null && this.baseClass.IsReferenceType);
  11689. }
  11690. }
  11691. private bool isUnmanagedIsValid = false;
  11692. private bool isUnmanaged = false;
  11693. public override bool IsUnmanaged{
  11694. get{
  11695. if (!isUnmanagedIsValid && SystemTypes.UnmanagedStructTemplateParameterAttribute != null){
  11696. // check if we have the corresponding attribute
  11697. for (int i=0; i < (this.Attributes == null?0:this.Attributes.Count); i++){
  11698. if (this.Attributes[i].Type == SystemTypes.UnmanagedStructTemplateParameterAttribute){
  11699. isUnmanaged = true;
  11700. break;
  11701. }
  11702. }
  11703. #if ExtendedRuntime
  11704. if (!isUnmanaged) { isUnmanaged = IsPointerFree; }
  11705. #endif
  11706. isUnmanagedIsValid = true;
  11707. }
  11708. return isUnmanaged;
  11709. }
  11710. }
  11711. public void SetIsUnmanaged(){
  11712. this.isUnmanaged = true;
  11713. this.isUnmanagedIsValid = true;
  11714. }
  11715. private bool isPointerFreeIsValid = false;
  11716. private bool isPointerFree = false;
  11717. public override bool IsPointerFree
  11718. {
  11719. get
  11720. {
  11721. if (!isPointerFreeIsValid && SystemTypes.PointerFreeStructTemplateParameterAttribute != null)
  11722. {
  11723. // check if we have the corresponding attribute
  11724. for (int i = 0; i < (this.Attributes == null ? 0 : this.Attributes.Count); i++)
  11725. {
  11726. if (this.Attributes[i].Type == SystemTypes.PointerFreeStructTemplateParameterAttribute)
  11727. {
  11728. isPointerFree = true;
  11729. break;
  11730. }
  11731. }
  11732. isPointerFreeIsValid = true;
  11733. }
  11734. return isPointerFree;
  11735. }
  11736. }
  11737. public void SetIsPointerFree()
  11738. {
  11739. this.isPointerFree = true;
  11740. this.isPointerFreeIsValid = true;
  11741. // pointerfree implies Unmanaged
  11742. SetIsUnmanaged();
  11743. }
  11744. #endif
  11745. #if !NoXml
  11746. public override XmlNode Documentation{
  11747. get{
  11748. if (this.documentation == null && this.declaringMember != null && this.Name != null){
  11749. XmlNode parentDoc = this.declaringMember.Documentation;
  11750. if (parentDoc != null && parentDoc.HasChildNodes){
  11751. string myName = this.Name.Name;
  11752. foreach (XmlNode child in parentDoc.ChildNodes){
  11753. if (child.Name == "typeparam" && child.Attributes != null){
  11754. foreach (XmlAttribute attr in child.Attributes){
  11755. if (attr != null && attr.Name == "name" && attr.Value == myName)
  11756. return this.documentation = child;
  11757. }
  11758. }
  11759. }
  11760. }
  11761. }
  11762. return this.documentation;
  11763. }
  11764. set{
  11765. this.documentation = value;
  11766. }
  11767. }
  11768. public override string HelpText{
  11769. get{
  11770. if (this.helpText == null){
  11771. XmlNode doc = this.Documentation;
  11772. if (doc != null) this.helpText = doc.InnerText;
  11773. }
  11774. return this.helpText;
  11775. }
  11776. set{
  11777. this.helpText = value;
  11778. }
  11779. }
  11780. #endif
  11781. protected internal TypeNodeList structuralElementTypes;
  11782. public override TypeNodeList StructuralElementTypes{
  11783. get{
  11784. TypeNodeList result = this.structuralElementTypes;
  11785. if (result != null) return result;
  11786. this.structuralElementTypes = result = new TypeNodeList();
  11787. if (this.BaseType != null) result.Add(this.BaseType);
  11788. InterfaceList interfaces = this.Interfaces;
  11789. for (int i = 0, n = interfaces == null ? 0 : interfaces.Count; i < n; i++){
  11790. Interface iface = interfaces[i];
  11791. if (iface == null) continue;
  11792. result.Add(iface);
  11793. }
  11794. return result;
  11795. }
  11796. }
  11797. #if !NoXml
  11798. internal override void AppendDocumentIdMangledName(StringBuilder/*!*/ sb, TypeNodeList methodTypeParameters, TypeNodeList typeParameters) {
  11799. if (TargetPlatform.GenericTypeNamesMangleChar != 0) {
  11800. int n = methodTypeParameters == null ? 0 : methodTypeParameters.Count;
  11801. for (int i = 0; i < n; i++){
  11802. //^ assert methodTypeParameters != null;
  11803. TypeNode mpar = methodTypeParameters[i];
  11804. if (mpar != this) continue;
  11805. sb.Append(TargetPlatform.GenericTypeNamesMangleChar);
  11806. sb.Append(TargetPlatform.GenericTypeNamesMangleChar);
  11807. sb.Append(i);
  11808. return;
  11809. }
  11810. n = typeParameters == null ? 0 : typeParameters.Count;
  11811. for (int i = 0; i < n; i++){
  11812. TypeNode tpar = typeParameters[i];
  11813. if (tpar != this) continue;
  11814. sb.Append(TargetPlatform.GenericTypeNamesMangleChar);
  11815. sb.Append(i);
  11816. return;
  11817. }
  11818. sb.Append("not found:");
  11819. }
  11820. sb.Append(this.FullName);
  11821. }
  11822. #endif
  11823. public override string GetFullUnmangledNameWithoutTypeParameters(){
  11824. return this.GetUnmangledNameWithoutTypeParameters();
  11825. }
  11826. public override string GetFullUnmangledNameWithTypeParameters(){
  11827. return this.GetUnmangledNameWithTypeParameters();
  11828. }
  11829. public override bool IsStructurallyEquivalentTo(TypeNode type){
  11830. if (null == (object)type) return false;
  11831. if (this == type) return true;
  11832. ITypeParameter itype = type as ITypeParameter;
  11833. if (null == (object)itype) return false;
  11834. if (this.Name != null && type.Name != null && this.Name.UniqueIdKey != type.Name.UniqueIdKey){
  11835. if (this.DeclaringMember == itype.DeclaringMember) return false;
  11836. }
  11837. TypeNode bType = this.BaseType;
  11838. TypeNode tbType = type.BaseType;
  11839. if (null == (object)bType) bType = CoreSystemTypes.Object;
  11840. if (null == (object)tbType) tbType = CoreSystemTypes.Object;
  11841. if (bType != tbType /*&& !bType.IsStructurallyEquivalentTo(tbType)*/) return false;
  11842. if (this.Interfaces == null) return type.Interfaces == null || type.Interfaces.Count == 0;
  11843. if (type.Interfaces == null) return this.Interfaces.Count == 0;
  11844. int n = this.Interfaces.Count; if (n != type.Interfaces.Count) return false;
  11845. for (int i = 0; i < n; i++){
  11846. Interface i1 = this.Interfaces[i];
  11847. Interface i2 = type.Interfaces[i];
  11848. if (null == (object)i1 || null == (object)i2) return false;
  11849. if (i1 != i2 /*&& !i1.IsStructurallyEquivalentTo(i2)*/) return false;
  11850. }
  11851. return true;
  11852. }
  11853. #if !MinimalReader
  11854. SourceContext ITypeParameter.SourceContext { get { return this.SourceContext; } }
  11855. Module ITypeParameter.DeclaringModule { get { return this.DeclaringModule; } }
  11856. TypeFlags ITypeParameter.Flags { get { return this.Flags; } }
  11857. #endif
  11858. #if FxCop
  11859. internal override void GetName(TypeFormat options, StringBuilder name)
  11860. {
  11861. if (options.TypeName == TypeNameFormat.FullyQualified)
  11862. {
  11863. TypeFormat typeFormat = options.Clone();
  11864. typeFormat.TypeName = TypeNameFormat.Short;
  11865. base.GetName(typeFormat, name);
  11866. return;
  11867. }
  11868. base.GetName(options, name);
  11869. }
  11870. #endif
  11871. }
  11872. public class MethodClassParameter : ClassParameter{
  11873. public MethodClassParameter()
  11874. : base(){
  11875. this.NodeType = NodeType.ClassParameter;
  11876. this.baseClass = CoreSystemTypes.Object;
  11877. this.Flags = TypeFlags.NestedPublic|TypeFlags.Abstract;
  11878. this.Namespace = StandardIds.TypeParameter;
  11879. }
  11880. #if !NoReflection && WHIDBEY
  11881. public override Type GetRuntimeType() {
  11882. Method m = this.DeclaringMember as Method;
  11883. if (m == null) return null;
  11884. System.Reflection.MethodInfo mi = m.GetMethodInfo();
  11885. if (mi == null) return null;
  11886. System.Type[] typeParameters = mi.GetGenericArguments();
  11887. if (this.ParameterListIndex >= typeParameters.Length) return null;
  11888. return typeParameters[this.ParameterListIndex];
  11889. }
  11890. #endif
  11891. #if !MinimalReader
  11892. public override bool IsStructurallyEquivalentTo(TypeNode type) {
  11893. if (object.ReferenceEquals(this, type)) return true;
  11894. ITypeParameter tp = type as ITypeParameter;
  11895. if (tp == null) return false;
  11896. if (this.ParameterListIndex == tp.ParameterListIndex /* && this.DeclaringMember == tp.DeclaringMember*/) return true;
  11897. return base.IsStructurallyEquivalentTo(type as MethodClassParameter);
  11898. }
  11899. #endif
  11900. }
  11901. public class ArrayType : TypeNode{
  11902. private TypeNode/*!*/ elementType;
  11903. private int rank;
  11904. private int[] lowerBounds;
  11905. private int[] sizes;
  11906. internal ArrayType()
  11907. : base(NodeType.ArrayType){
  11908. }
  11909. internal ArrayType(TypeNode/*!*/ elementType, int rank)
  11910. : this(elementType, rank, new int[0], new int[0]){
  11911. if (rank == 1)
  11912. this.typeCode = Metadata.ElementType.SzArray;
  11913. else
  11914. this.typeCode = Metadata.ElementType.Array;
  11915. }
  11916. internal ArrayType(TypeNode/*!*/ elementType, int rank, int[] sizes)
  11917. : this(elementType, rank, sizes, new int[0]){
  11918. }
  11919. internal ArrayType(TypeNode/*!*/ elementType, int rank, int[] sizes, int[] lowerBounds)
  11920. : base(null, null, null, elementType.Flags, null, null, null, null, NodeType.ArrayType){
  11921. Debug.Assert(elementType != null);
  11922. this.rank = rank;
  11923. this.elementType = elementType;
  11924. this.DeclaringModule = elementType.DeclaringModule;
  11925. this.lowerBounds = lowerBounds;
  11926. this.sizes = sizes;
  11927. if (rank == 1)
  11928. this.typeCode = Metadata.ElementType.SzArray;
  11929. else
  11930. this.typeCode = Metadata.ElementType.Array;
  11931. if (elementType == null || elementType.Name == null) return;
  11932. StringBuilder name = new StringBuilder(this.ElementType.Name.ToString());
  11933. #if FxCop
  11934. GetNameSuffix(name, false);
  11935. #else
  11936. name.Append('[');
  11937. int k = this.Sizes == null ? 0 : this.Sizes.Length;
  11938. int m = this.LowerBounds == null ? 0 : this.LowerBounds.Length;
  11939. for (int i = 0, n = this.Rank; i < n; i++){
  11940. if (i < k && this.Sizes[i] != 0){
  11941. if (i < m && this.LowerBounds[i] != 0){
  11942. name.Append(this.LowerBounds[i]);
  11943. name.Append(':');
  11944. }
  11945. name.Append(this.Sizes[i]);
  11946. }
  11947. if (i < n-1)
  11948. name.Append(',');
  11949. }
  11950. name.Append(']');
  11951. #endif
  11952. this.Name = Identifier.For(name.ToString());
  11953. this.Namespace = elementType.Namespace;
  11954. }
  11955. public TypeNode/*!*/ ElementType {
  11956. get{return this.elementType;}
  11957. set{this.elementType = value;}
  11958. }
  11959. /// <summary>The interfaces implemented by this class or struct, or the extended by this interface.</summary>
  11960. public override InterfaceList Interfaces {
  11961. get {
  11962. if (this.interfaces == null) {
  11963. InterfaceList interfaces = new InterfaceList(SystemTypes.ICloneable, SystemTypes.IList, SystemTypes.ICollection, SystemTypes.IEnumerable);
  11964. if (this.Rank == 1) {
  11965. if (SystemTypes.GenericIEnumerable != null && SystemTypes.GenericIEnumerable.DeclaringModule == CoreSystemTypes.SystemAssembly) {
  11966. interfaces.Add((Interface)SystemTypes.GenericIEnumerable.GetTemplateInstance(this, elementType));
  11967. if (SystemTypes.GenericICollection != null)
  11968. interfaces.Add((Interface)SystemTypes.GenericICollection.GetTemplateInstance(this, elementType));
  11969. if (SystemTypes.GenericIList != null)
  11970. interfaces.Add((Interface)SystemTypes.GenericIList.GetTemplateInstance(this, elementType));
  11971. }
  11972. }
  11973. this.interfaces = interfaces;
  11974. }
  11975. return this.interfaces;
  11976. }
  11977. set { this.interfaces = value; }
  11978. }
  11979. public int Rank {
  11980. get{return this.rank;}
  11981. set{this.rank = value;}
  11982. }
  11983. public int[] LowerBounds{
  11984. get{return this.lowerBounds;}
  11985. set{this.lowerBounds = value;}
  11986. }
  11987. public int[] Sizes{
  11988. get{return this.sizes;}
  11989. set{this.sizes = value;}
  11990. }
  11991. public bool IsSzArray(){
  11992. return this.typeCode == Metadata.ElementType.SzArray;
  11993. }
  11994. private MemberList ctorList = null;
  11995. private MemberList getterList = null;
  11996. private MemberList setterList = null;
  11997. private MemberList addressList = null;
  11998. public override MemberList Members{
  11999. get{
  12000. if (this.members == null || this.membersBeingPopulated){
  12001. lock(this){
  12002. if (this.members == null){
  12003. this.membersBeingPopulated = true;
  12004. MemberList members = this.members = new MemberList(5);
  12005. members.Add(this.Constructor);
  12006. //^ assume this.ctorList != null && this.ctorList.Length > 1;
  12007. members.Add(this.ctorList[1]);
  12008. members.Add(this.Getter);
  12009. members.Add(this.Setter);
  12010. members.Add(this.Address);
  12011. this.membersBeingPopulated = false;
  12012. }
  12013. }
  12014. }
  12015. return this.members;
  12016. }
  12017. set{
  12018. this.members = value;
  12019. }
  12020. }
  12021. public override string/*!*/ FullName {
  12022. get{
  12023. if (this.ElementType != null && this.ElementType.DeclaringType != null)
  12024. return this.ElementType.DeclaringType.FullName+"+"+(this.Name == null ? "" : this.Name.ToString());
  12025. else if (this.Namespace != null && this.Namespace.UniqueIdKey != Identifier.Empty.UniqueIdKey)
  12026. return this.Namespace.ToString() + "."+(this.Name == null ? "" : this.Name.ToString());
  12027. else if (this.Name != null)
  12028. return this.Name.ToString();
  12029. else
  12030. return "";
  12031. }
  12032. }
  12033. #if !NoXml
  12034. internal override void AppendDocumentIdMangledName(StringBuilder/*!*/ sb, TypeNodeList methodTypeParameters, TypeNodeList typeParameters) {
  12035. if (this.ElementType == null) return;
  12036. this.ElementType.AppendDocumentIdMangledName(sb, methodTypeParameters, typeParameters);
  12037. sb.Append('[');
  12038. int k = this.Sizes == null ? 0 : this.Sizes.Length;
  12039. int m = this.LowerBounds == null ? 0 : this.LowerBounds.Length;
  12040. for (int i = 0, n = this.Rank; i < n; i++){
  12041. if (i < k && this.Sizes[i] != 0){
  12042. if (i < m && this.LowerBounds[i] != 0){
  12043. sb.Append(this.LowerBounds[i]);
  12044. sb.Append(':');
  12045. }
  12046. sb.Append(this.Sizes[i]);
  12047. }
  12048. if (i < n-1)
  12049. sb.Append(',');
  12050. }
  12051. sb.Append(']');
  12052. }
  12053. #endif
  12054. public virtual void SetLowerBoundToUnknown(){
  12055. Debug.Assert(this.Rank == 1);
  12056. this.typeCode = Metadata.ElementType.Array;
  12057. }
  12058. public virtual int GetLowerBound(int dimension){
  12059. if (this.LowerBounds == null || this.LowerBounds.Length <= dimension) return 0;
  12060. return this.LowerBounds[dimension];
  12061. }
  12062. public virtual int GetSize(int dimension){
  12063. if (this.Sizes == null || this.Sizes.Length <= dimension) return 0;
  12064. return this.Sizes[dimension];
  12065. }
  12066. public override MemberList/*!*/ GetMembersNamed(Identifier name) {
  12067. if (name == null) return new MemberList(0);
  12068. if (name.UniqueIdKey == StandardIds.Get.UniqueIdKey){
  12069. if (this.getterList == null){
  12070. Method getter = this.Getter;
  12071. if (getter != null) getter = null;
  12072. //^ assume this.getterList != null;
  12073. }
  12074. return this.getterList;
  12075. }else if (name.UniqueIdKey == StandardIds.Set.UniqueIdKey){
  12076. if (this.setterList == null){
  12077. Method setter = this.Setter;
  12078. if (setter != null) setter = null;
  12079. //^ assume this.setterList != null;
  12080. }
  12081. return this.setterList;
  12082. }else if (name.UniqueIdKey == StandardIds.Ctor.UniqueIdKey){
  12083. if (this.ctorList == null){
  12084. Method ctor = this.Constructor;
  12085. if (ctor != null) ctor = null;
  12086. //^ assume this.ctorList != null;
  12087. }
  12088. return this.ctorList;
  12089. }else if (name.UniqueIdKey == StandardIds.Address.UniqueIdKey){
  12090. if (this.addressList == null){
  12091. Method addr = this.Address;
  12092. if (addr != null) addr = null;
  12093. //^ assume this.addressList != null;
  12094. }
  12095. return this.addressList;
  12096. }else
  12097. return new MemberList(0);
  12098. }
  12099. #if !NoReflection
  12100. public override Type GetRuntimeType(){
  12101. if (this.runtimeType == null){
  12102. if (this.ElementType == null) return null;
  12103. Type eType = this.ElementType.GetRuntimeType();
  12104. if (eType == null) return null;
  12105. #if WHIDBEY
  12106. if (this.IsSzArray())
  12107. this.runtimeType = eType.MakeArrayType();
  12108. else
  12109. this.runtimeType = eType.MakeArrayType(this.Rank);
  12110. #else
  12111. StringBuilder sb = new StringBuilder(eType.FullName);
  12112. sb.Append('[');
  12113. for (int i = 1, n = this.Rank; i < n; i++) sb.Append(',');
  12114. sb.Append(']');
  12115. if (eType.Assembly != null)
  12116. this.runtimeType = eType.Assembly.GetType(sb.ToString(), false);
  12117. else if (eType.Module != null)
  12118. this.runtimeType = eType.Module.GetType(sb.ToString(), false);
  12119. #endif
  12120. }
  12121. return this.runtimeType;
  12122. }
  12123. #endif
  12124. public Method Constructor{
  12125. get{
  12126. if (this.ctorList == null){
  12127. lock(this){
  12128. if (this.ctorList == null){
  12129. InstanceInitializer ctor = new InstanceInitializer();
  12130. ctor.DeclaringType = this;
  12131. ctor.Flags |= MethodFlags.Public;
  12132. int n = this.Rank;
  12133. ctor.Parameters = new ParameterList(n);
  12134. for (int i = 0; i < n; i++){
  12135. Parameter par = new Parameter();
  12136. par.DeclaringMethod = ctor;
  12137. par.Type = CoreSystemTypes.Int32;
  12138. ctor.Parameters.Add(par);
  12139. }
  12140. this.ctorList = new MemberList(2);
  12141. this.ctorList.Add(ctor);
  12142. ctor = new InstanceInitializer();
  12143. ctor.DeclaringType = this;
  12144. ctor.Flags |= MethodFlags.Public;
  12145. ctor.Parameters = new ParameterList(n=n*2);
  12146. for (int i = 0; i < n; i++){
  12147. Parameter par = new Parameter();
  12148. par.Type = CoreSystemTypes.Int32;
  12149. par.DeclaringMethod = ctor;
  12150. ctor.Parameters.Add(par);
  12151. }
  12152. this.ctorList.Add(ctor);
  12153. }
  12154. }
  12155. }
  12156. return (Method)this.ctorList[0];
  12157. }
  12158. }
  12159. public Method Getter{
  12160. get{
  12161. if (this.getterList == null){
  12162. lock(this){
  12163. if (this.getterList == null){
  12164. Method getter = new Method();
  12165. getter.Name = StandardIds.Get;
  12166. getter.DeclaringType = this;
  12167. getter.CallingConvention = CallingConventionFlags.HasThis;
  12168. getter.Flags = MethodFlags.Public;
  12169. getter.Parameters = new ParameterList();
  12170. for (int i = 0, n = this.Rank; i < n; i++){
  12171. Parameter par = new Parameter();
  12172. par.Type = CoreSystemTypes.Int32;
  12173. par.DeclaringMethod = getter;
  12174. getter.Parameters.Add(par);
  12175. }
  12176. getter.ReturnType = this.ElementType;
  12177. this.getterList = new MemberList();
  12178. this.getterList.Add(getter);
  12179. }
  12180. }
  12181. }
  12182. return (Method)this.getterList[0];
  12183. }
  12184. }
  12185. public Method Setter{
  12186. get{
  12187. if (this.setterList == null){
  12188. lock(this){
  12189. if (this.setterList == null){
  12190. Method setter = new Method();
  12191. setter.Name = StandardIds.Set;
  12192. setter.DeclaringType = this;
  12193. setter.CallingConvention = CallingConventionFlags.HasThis;
  12194. setter.Flags = MethodFlags.Public;
  12195. setter.Parameters = new ParameterList();
  12196. Parameter par;
  12197. for (int i = 0, n = this.Rank; i < n; i++){
  12198. par = new Parameter();
  12199. par.Type = CoreSystemTypes.Int32;
  12200. par.DeclaringMethod = setter;
  12201. setter.Parameters.Add(par);
  12202. }
  12203. par = new Parameter();
  12204. par.Type = this.ElementType;
  12205. par.DeclaringMethod = setter;
  12206. setter.Parameters.Add(par);
  12207. setter.ReturnType = CoreSystemTypes.Void;
  12208. this.setterList = new MemberList();
  12209. this.setterList.Add(setter);
  12210. }
  12211. }
  12212. }
  12213. return (Method)this.setterList[0];
  12214. }
  12215. }
  12216. public Method Address{
  12217. get{
  12218. if (this.addressList == null){
  12219. lock(this){
  12220. if (this.addressList == null){
  12221. Method address = new Method();
  12222. address.Name = StandardIds.Address;
  12223. address.DeclaringType = this;
  12224. address.CallingConvention = CallingConventionFlags.HasThis;
  12225. address.Flags = MethodFlags.Public;
  12226. address.Parameters = new ParameterList();
  12227. for (int i = 0, n = this.Rank; i < n; i++){
  12228. Parameter par = new Parameter();
  12229. par.Type = CoreSystemTypes.Int32;
  12230. par.DeclaringMethod = address;
  12231. address.Parameters.Add(par);
  12232. }
  12233. address.ReturnType = this.ElementType.GetReferenceType();
  12234. this.addressList = new MemberList();
  12235. this.addressList.Add(address);
  12236. }
  12237. }
  12238. }
  12239. return (Method)this.addressList[0];
  12240. }
  12241. }
  12242. public override bool IsAssignableTo(TypeNode targetType){
  12243. if (targetType == null) return false;
  12244. if (targetType == this || targetType == CoreSystemTypes.Object || targetType == CoreSystemTypes.Array || targetType == SystemTypes.ICloneable) return true;
  12245. if (CoreSystemTypes.Array.IsAssignableTo(targetType)) return true;
  12246. if (targetType.Template != null && SystemTypes.GenericIEnumerable != null && SystemTypes.GenericIEnumerable.DeclaringModule == CoreSystemTypes.SystemAssembly) {
  12247. if (targetType.Template == SystemTypes.GenericIEnumerable || targetType.Template == SystemTypes.GenericICollection ||
  12248. targetType.Template == SystemTypes.GenericIList) {
  12249. if (targetType.TemplateArguments == null || targetType.TemplateArguments.Count != 1) {
  12250. Debug.Assert(false); return false;
  12251. }
  12252. TypeNode ienumElementType = targetType.TemplateArguments[0];
  12253. if (this.ElementType == ienumElementType) return true;
  12254. if (this.ElementType.IsValueType) return false;
  12255. return this.ElementType.IsAssignableTo(ienumElementType);
  12256. }
  12257. }
  12258. ArrayType targetArrayType = targetType as ArrayType;
  12259. if (targetArrayType == null) return false;
  12260. if (this.Rank != 1 || targetArrayType.Rank != 1) return false;
  12261. TypeNode thisElementType = this.ElementType;
  12262. if (thisElementType == null) return false;
  12263. #if ExtendedRuntime
  12264. thisElementType = TypeNode.StripModifier(thisElementType, ExtendedRuntimeTypes.NonNullType);
  12265. // DelayedAttribute is used as a modifier on some array allocation types to mark it as
  12266. // an explictly delayed allocation.
  12267. thisElementType = TypeNode.StripModifier(thisElementType, ExtendedRuntimeTypes.DelayedAttribute);
  12268. #endif
  12269. if (thisElementType == targetArrayType.ElementType) return true;
  12270. if (thisElementType.IsValueType) return false;
  12271. return thisElementType.IsAssignableTo(targetArrayType.ElementType);
  12272. }
  12273. public override bool IsStructural{
  12274. get{return true;}
  12275. }
  12276. protected TypeNodeList structuralElementTypes;
  12277. public override TypeNodeList StructuralElementTypes{
  12278. get{
  12279. TypeNodeList result = this.structuralElementTypes;
  12280. if (result != null) return result;
  12281. this.structuralElementTypes = result = new TypeNodeList(1);
  12282. result.Add(this.ElementType);
  12283. return result;
  12284. }
  12285. }
  12286. public override bool IsStructurallyEquivalentTo(TypeNode type){
  12287. if (type == null) return false;
  12288. if (this == type) return true;
  12289. ArrayType t = type as ArrayType;
  12290. if (t == null) return false;
  12291. if (this.Rank != t.Rank) return false;
  12292. if (this.ElementType == null || t.ElementType == null) return false;
  12293. if (this.ElementType != t.ElementType && !this.ElementType.IsStructurallyEquivalentTo(t.ElementType)) return false;
  12294. if (this.Sizes == null) return t.Sizes == null;
  12295. if (t.Sizes == null) return false;
  12296. int n = this.Sizes.Length; if (n != t.Sizes.Length) return false;
  12297. for (int i = 0; i < n; i++){
  12298. if (this.Sizes[i] != t.Sizes[i]) return false;
  12299. }
  12300. if (this.LowerBounds == null) return t.LowerBounds == null;
  12301. if (t.LowerBounds == null) return false;
  12302. n = this.LowerBounds.Length; if (n != t.LowerBounds.Length) return false;
  12303. for (int i = 0; i < n; i++){
  12304. if (this.LowerBounds[i] != t.LowerBounds[i]) return false;
  12305. }
  12306. return true;
  12307. }
  12308. #if FxCop
  12309. internal override void GetName(MemberFormat options, StringBuilder name)
  12310. {
  12311. this.ElementType.GetName(options, name);
  12312. GetNameSuffix(name, options.InsertSpacesBetweenMethodTypeParameters);
  12313. }
  12314. private void GetNameSuffix(StringBuilder name, bool insertSpacesBetweenParameters)
  12315. {
  12316. name.Append('[');
  12317. int k = this.Sizes == null ? 0 : this.Sizes.Length;
  12318. int m = this.LowerBounds == null ? 0 : this.LowerBounds.Length;
  12319. for (int i = 0, n = this.Rank; i < n; i++)
  12320. {
  12321. if (i < k && this.Sizes[i] != 0)
  12322. {
  12323. if (i < m && this.LowerBounds[i] != 0)
  12324. {
  12325. name.Append(this.LowerBounds[i].ToString("0", CultureInfo.InvariantCulture));
  12326. name.Append(':');
  12327. }
  12328. name.Append(this.Sizes[i].ToString("0", CultureInfo.InvariantCulture));
  12329. }
  12330. if (i < n - 1)
  12331. {
  12332. name.Append(',');
  12333. if (insertSpacesBetweenParameters)
  12334. name.Append(' ');
  12335. }
  12336. }
  12337. name.Append(']');
  12338. }
  12339. #endif
  12340. }
  12341. public class Pointer : TypeNode{
  12342. internal Pointer(TypeNode/*!*/ elementType)
  12343. : base(NodeType.Pointer){
  12344. this.elementType = elementType;
  12345. this.typeCode = Metadata.ElementType.Pointer;
  12346. this.Name = Identifier.For(elementType.Name+"*");
  12347. this.Namespace = elementType.Namespace;
  12348. }
  12349. private TypeNode/*!*/ elementType;
  12350. public TypeNode/*!*/ ElementType {
  12351. get{return this.elementType;}
  12352. set{this.elementType = value;}
  12353. }
  12354. public override string/*!*/ FullName {
  12355. get{
  12356. if (this.ElementType != null && this.ElementType.DeclaringType != null)
  12357. return this.ElementType.DeclaringType.FullName+"+"+(this.Name == null ? "" : this.Name.ToString());
  12358. else if (this.Namespace != null && this.Namespace.UniqueIdKey != Identifier.Empty.UniqueIdKey)
  12359. return this.Namespace.ToString()+"."+(this.Name == null ? "" : this.Name.ToString());
  12360. else if (this.Name != null)
  12361. return this.Name.ToString();
  12362. else
  12363. return "";
  12364. }
  12365. }
  12366. #if !NoXml
  12367. internal override void AppendDocumentIdMangledName(StringBuilder/*!*/ sb, TypeNodeList methodTypeParameters, TypeNodeList typeParameters) {
  12368. if (this.elementType == null) return;
  12369. this.elementType.AppendDocumentIdMangledName(sb, methodTypeParameters, typeParameters);
  12370. sb.Append('*');
  12371. }
  12372. #endif
  12373. #if !NoReflection
  12374. public override Type GetRuntimeType(){
  12375. if (this.runtimeType == null){
  12376. if (this.ElementType == null) return null;
  12377. Type eType = this.ElementType.GetRuntimeType();
  12378. if (eType == null) return null;
  12379. #if WHIDBEY
  12380. this.runtimeType = eType.MakePointerType();
  12381. #else
  12382. if (eType.Assembly != null)
  12383. this.runtimeType = eType.Assembly.GetType(eType.FullName+"*", false);
  12384. else
  12385. this.runtimeType = eType.Module.GetType(eType.FullName+"*", false);
  12386. #endif
  12387. }
  12388. return this.runtimeType;
  12389. }
  12390. #endif
  12391. public override bool IsAssignableTo(TypeNode targetType){
  12392. return targetType == this || (targetType is Pointer && ((Pointer)targetType).ElementType == CoreSystemTypes.Void);
  12393. }
  12394. public override bool IsUnmanaged{
  12395. get{
  12396. return true;
  12397. }
  12398. }
  12399. public override bool IsStructural{
  12400. get{return true;}
  12401. }
  12402. public override bool IsPointerType {
  12403. get {
  12404. return true;
  12405. }
  12406. }
  12407. protected TypeNodeList structuralElementTypes;
  12408. public override TypeNodeList StructuralElementTypes{
  12409. get{
  12410. TypeNodeList result = this.structuralElementTypes;
  12411. if (result != null) return result;
  12412. this.structuralElementTypes = result = new TypeNodeList(1);
  12413. result.Add(this.ElementType);
  12414. return result;
  12415. }
  12416. }
  12417. public override bool IsStructurallyEquivalentTo(TypeNode type){
  12418. if (type == null) return false;
  12419. if (this == type) return true;
  12420. Pointer t = type as Pointer;
  12421. if (t == null) return false;
  12422. if (this.ElementType == null || t.ElementType == null) return false;
  12423. return this.ElementType == t.ElementType || this.ElementType.IsStructurallyEquivalentTo(t.ElementType);
  12424. }
  12425. #if FxCop
  12426. internal override void GetName(TypeFormat options, StringBuilder name)
  12427. {
  12428. this.ElementType.GetName(options, name);
  12429. name.Append('*');
  12430. }
  12431. #endif
  12432. }
  12433. public class Reference : TypeNode{
  12434. internal Reference(TypeNode/*!*/ elementType)
  12435. : base(NodeType.Reference){
  12436. this.elementType = elementType;
  12437. this.typeCode = Metadata.ElementType.Reference;
  12438. this.Name = Identifier.For(elementType.Name+"@");
  12439. this.Namespace = elementType.Namespace;
  12440. }
  12441. private TypeNode/*!*/ elementType;
  12442. public TypeNode/*!*/ ElementType {
  12443. get{return this.elementType;}
  12444. set{this.elementType = value;}
  12445. }
  12446. #if !NoXml
  12447. internal override void AppendDocumentIdMangledName(StringBuilder/*!*/ sb, TypeNodeList methodTypeParameters, TypeNodeList typeParameters) {
  12448. if (this.elementType == null) return;
  12449. this.elementType.AppendDocumentIdMangledName(sb, methodTypeParameters, typeParameters);
  12450. sb.Append('@');
  12451. }
  12452. #endif
  12453. public override bool IsAssignableTo(TypeNode targetType){
  12454. return targetType == this ||
  12455. (targetType is Pointer && (((Pointer)targetType).ElementType == this.ElementType ||
  12456. ((Pointer)targetType).ElementType == CoreSystemTypes.Void));
  12457. }
  12458. public override string/*!*/ FullName {
  12459. get{
  12460. if (this.ElementType != null && this.ElementType.DeclaringType != null)
  12461. return this.ElementType.DeclaringType.FullName+"+"+(this.Name == null ? "" : this.Name.ToString());
  12462. else if (this.Namespace != null && this.Namespace.UniqueIdKey != Identifier.Empty.UniqueIdKey)
  12463. return this.Namespace.ToString()+"."+(this.Name == null ? "" : this.Name.ToString());
  12464. else if (this.Name != null)
  12465. return this.Name.ToString();
  12466. else
  12467. return "";
  12468. }
  12469. }
  12470. #if !NoReflection
  12471. public override Type GetRuntimeType(){
  12472. if (this.runtimeType == null){
  12473. if (this.ElementType == null) return null;
  12474. Type eType = this.ElementType.GetRuntimeType();
  12475. if (eType == null) return null;
  12476. #if WHIDBEY
  12477. this.runtimeType = eType.MakeByRefType();
  12478. #else
  12479. if (eType.Assembly != null)
  12480. this.runtimeType = eType.Assembly.GetType(eType.FullName+"&", false);
  12481. else
  12482. this.runtimeType = eType.Module.GetType(eType.FullName+"&", false);
  12483. #endif
  12484. }
  12485. return this.runtimeType;
  12486. }
  12487. #endif
  12488. public override bool IsStructural{
  12489. get{return true;}
  12490. }
  12491. protected TypeNodeList structuralElementTypes;
  12492. public override TypeNodeList StructuralElementTypes{
  12493. get{
  12494. TypeNodeList result = this.structuralElementTypes;
  12495. if (result != null) return result;
  12496. this.structuralElementTypes = result = new TypeNodeList(1);
  12497. result.Add(this.ElementType);
  12498. return result;
  12499. }
  12500. }
  12501. public override bool IsStructurallyEquivalentTo(TypeNode type){
  12502. if (type == null) return false;
  12503. if (this == type) return true;
  12504. Reference t = type as Reference;
  12505. if (t == null) return false;
  12506. if (this.ElementType == null || t.ElementType == null) return false;
  12507. return this.ElementType == t.ElementType || this.ElementType.IsStructurallyEquivalentTo(t.ElementType);
  12508. }
  12509. #if FxCop
  12510. internal override void GetName(TypeFormat options, StringBuilder name)
  12511. {
  12512. this.ElementType.GetName(options, name);
  12513. name.Append('&');
  12514. }
  12515. #endif
  12516. }
  12517. #if ExtendedRuntime
  12518. public class TupleType : Struct{
  12519. private TupleType(FieldList domains, Identifier/*!*/ name, TypeNode/*!*/ referringType, TypeFlags visibility) {
  12520. referringType.DeclaringModule.StructurallyEquivalentType[name.UniqueIdKey] = this;
  12521. this.DeclaringModule = referringType.DeclaringModule;
  12522. this.NodeType = NodeType.TupleType;
  12523. this.Flags = TypeFlags.Sealed;
  12524. this.Namespace = StandardIds.StructuralTypes;
  12525. this.Name = name;
  12526. this.isNormalized = true;
  12527. switch (visibility){
  12528. case TypeFlags.NestedFamANDAssem:
  12529. case TypeFlags.NestedFamily:
  12530. case TypeFlags.NestedPrivate:
  12531. referringType.Members.Add(this);
  12532. this.DeclaringType = referringType;
  12533. this.Flags |= TypeFlags.NestedPrivate;
  12534. break;
  12535. default:
  12536. referringType.DeclaringModule.Types.Add(this);
  12537. this.Flags |= TypeFlags.Public;
  12538. break;
  12539. }
  12540. int n = domains == null ? 0 : domains.Count;
  12541. MemberList members = this.members = new MemberList(n);
  12542. TypeNodeList types = new TypeNodeList(n);
  12543. for (int i = 0; i < n; i++){
  12544. //^ assert domains != null;
  12545. Field f = domains[i];
  12546. if (f == null) continue;
  12547. f = (Field)f.Clone();
  12548. f.DeclaringType = this;
  12549. members.Add(f);
  12550. if (f.Type != null)
  12551. types.Add(f.Type);
  12552. }
  12553. TypeNode elemType = null;
  12554. if (n == 1)
  12555. elemType = types[0]; //TODO: get element type of stream?
  12556. else{
  12557. TypeUnion tu = TypeUnion.For(types, referringType);
  12558. //^ assume tu != null;
  12559. elemType = tu;
  12560. if (tu.Types.Count == 1) elemType = tu.Types[0];
  12561. }
  12562. if (elemType == null) elemType = CoreSystemTypes.Object;
  12563. Interface ienumerable = (Interface)SystemTypes.GenericIEnumerable.GetTemplateInstance(referringType, elemType);
  12564. Interface ienumerator = (Interface)SystemTypes.GenericIEnumerator.GetTemplateInstance(referringType, elemType);
  12565. this.Interfaces = new InterfaceList(SystemTypes.TupleType, ienumerable, SystemTypes.IEnumerable);
  12566. This ThisParameter = new This(this.GetReferenceType());
  12567. StatementList statements = new StatementList(1);
  12568. TypeNode tEnumerator = TupleEnumerator.For(this, n, elemType, ienumerator, referringType);
  12569. InstanceInitializer cons = tEnumerator.GetConstructor(this);
  12570. if (cons == null) { Debug.Fail(""); return; }
  12571. ExpressionList args = new ExpressionList(new AddressDereference(ThisParameter, this));
  12572. statements.Add(new Return(new Construct(new MemberBinding(null, cons), args)));
  12573. Block body = new Block(statements);
  12574. Method getEnumerator = new Method(this, null, StandardIds.GetEnumerator, null, ienumerator, body);
  12575. getEnumerator.Flags = MethodFlags.Public|MethodFlags.Virtual;
  12576. getEnumerator.CallingConvention = CallingConventionFlags.HasThis;
  12577. getEnumerator.ThisParameter = ThisParameter;
  12578. this.members.Add(getEnumerator);
  12579. //IEnumerable.GetEnumerator
  12580. ThisParameter = new This(this.GetReferenceType());
  12581. statements = new StatementList(1);
  12582. MethodCall mcall = new MethodCall(new MemberBinding(ThisParameter, getEnumerator), new ExpressionList(0), NodeType.Call, SystemTypes.IEnumerator);
  12583. statements.Add(new Return(mcall));
  12584. getEnumerator = new Method(this, null, StandardIds.IEnumerableGetEnumerator, null, SystemTypes.IEnumerator, new Block(statements));
  12585. getEnumerator.ThisParameter = ThisParameter;
  12586. getEnumerator.ImplementedInterfaceMethods = new MethodList(SystemTypes.IEnumerable.GetMethod(StandardIds.GetEnumerator));
  12587. getEnumerator.CallingConvention = CallingConventionFlags.HasThis;
  12588. getEnumerator.Flags = MethodFlags.Private | MethodFlags.Virtual | MethodFlags.SpecialName;
  12589. this.members.Add(getEnumerator);
  12590. }
  12591. internal TupleType(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  12592. : base(provideNestedTypes, provideAttributes, provideMembers, handle) {
  12593. this.NodeType = NodeType.TupleType;
  12594. this.typeCode = ElementType.ValueType;
  12595. }
  12596. public static TupleType For(FieldList domains, TypeNode referringType){
  12597. if (referringType == null) return null;
  12598. Module module = referringType.DeclaringModule;
  12599. if (module == null) return null;
  12600. TypeFlags visibility = TypeFlags.Public;
  12601. StringBuilder name = new StringBuilder();
  12602. name.Append("Tuple");
  12603. int n = domains == null ? 0 : domains.Count;
  12604. for (int i = 0; i < n; i++) {
  12605. //^ assert domains != null;
  12606. Field f = domains[i];
  12607. if (f == null || f.Type == null || f.Type.Name == null) continue;
  12608. visibility = TypeNode.GetVisibilityIntersection(visibility, f.Type.Flags & TypeFlags.VisibilityMask);
  12609. name.Append('_');
  12610. name.Append(f.Type.Name.ToString());
  12611. if (f.Name != null && !f.IsSpecialName) {
  12612. name.Append('_');
  12613. name.Append(f.Name.ToString());
  12614. }
  12615. }
  12616. TupleType tup = null;
  12617. int tCount = 0;
  12618. string tNameString = name.ToString();
  12619. Identifier tName = Identifier.For(tNameString);
  12620. TypeNode result = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, tName);
  12621. while (result != null) {
  12622. //Mangled name is the same. But mangling is not unique (types are not qualified with assemblies), so check for equality.
  12623. tup = result as TupleType;
  12624. bool goodMatch = tup != null;
  12625. if (goodMatch) {
  12626. //^ assert tup != null;
  12627. MemberList tMembers = tup.Members;
  12628. int m = tMembers == null ? 0 : tMembers.Count;
  12629. goodMatch = n == m-2;
  12630. if (goodMatch) {
  12631. //^ assert domains != null;
  12632. //^ assert tMembers != null;
  12633. for (int i = 0; goodMatch && i < n; i++) {
  12634. Field f1 = domains[i];
  12635. Field f2 = tMembers[i] as Field;
  12636. goodMatch = f1 != null && f2 != null && f1.Type == f2.Type &&
  12637. f1.Name != null && f2.Name != null && f1.Name.UniqueIdKey == f2.Name.UniqueIdKey;
  12638. }
  12639. }
  12640. }
  12641. if (goodMatch) return tup;
  12642. //Mangle some more
  12643. tName = Identifier.For(tNameString+(++tCount).ToString());
  12644. result = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, tName);
  12645. }
  12646. tup = new TupleType(domains, tName, referringType, visibility);
  12647. return tup;
  12648. }
  12649. public override bool IsStructural{
  12650. get{return true;}
  12651. }
  12652. protected TypeNodeList structuralElementTypes;
  12653. public override TypeNodeList StructuralElementTypes{
  12654. get{
  12655. TypeNodeList result = this.structuralElementTypes;
  12656. if (result != null) return result;
  12657. this.structuralElementTypes = result = new TypeNodeList(1);
  12658. MemberList members = this.Members;
  12659. for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++){
  12660. Field f = members[i] as Field;
  12661. if (f == null || f.Type == null) continue;
  12662. result.Add(f.Type);
  12663. }
  12664. return result;
  12665. }
  12666. }
  12667. public override bool IsStructurallyEquivalentTo(TypeNode type){
  12668. if (type == null) return false;
  12669. if (this == type) return true;
  12670. TupleType t = type as TupleType;
  12671. if (t == null) return false;
  12672. if (this.Members == null) return t.Members == null;
  12673. if (t.Members == null) return false;
  12674. int n = this.Members.Count; if (n != t.Members.Count) return false;
  12675. for (int i = 0; i < n; i++){
  12676. Member m1 = this.Members[i];
  12677. Member m2 = t.Members[i];
  12678. if (m1 == null || m2 == null) return false;
  12679. Field f1 = m1 as Field;
  12680. Field f2 = m2 as Field;
  12681. if (f1 == null && f2 == null) continue;
  12682. if (f1 == null || f2 == null) return false;
  12683. if (f1.Name == null || f2.Name == null) return false;
  12684. if (f1.Type == null || f2.Type == null) return false;
  12685. if (f1.Name.UniqueIdKey != f2.Name.UniqueIdKey) return false;
  12686. if (f1.Type != f2.Type && !f1.Type.IsStructurallyEquivalentTo(f2.Type)) return false;
  12687. }
  12688. return true;
  12689. }
  12690. }
  12691. internal sealed class TupleEnumerator{
  12692. private TupleEnumerator(){}
  12693. internal static TypeNode/*!*/ For(TupleType/*!*/ tuple, int numDomains, TypeNode/*!*/ elementType, Interface/*!*/ targetIEnumerator, TypeNode/*!*/ referringType) {
  12694. Identifier id = Identifier.For("Enumerator"+tuple.Name);
  12695. InterfaceList interfaces = new InterfaceList(targetIEnumerator, SystemTypes.IDisposable, SystemTypes.IEnumerator);
  12696. MemberList members = new MemberList(5);
  12697. Class enumerator = new Class(referringType.DeclaringModule, null, null, TypeFlags.Sealed, targetIEnumerator.Namespace, id, CoreSystemTypes.Object, interfaces, members);
  12698. enumerator.IsNormalized = true;
  12699. if ((tuple.Flags & TypeFlags.VisibilityMask) == TypeFlags.Public){
  12700. enumerator.Flags |= TypeFlags.Public;
  12701. referringType.DeclaringModule.Types.Add(enumerator);
  12702. }else{
  12703. enumerator.Flags |= TypeFlags.NestedPrivate;
  12704. referringType.Members.Add(enumerator);
  12705. enumerator.DeclaringType = referringType;
  12706. }
  12707. //Field to hold tuple
  12708. Field tField = new Field(enumerator, null, FieldFlags.Private, StandardIds.Value, tuple, null);
  12709. members.Add(tField);
  12710. //Field to hold current position
  12711. Field pField = new Field(enumerator, null, FieldFlags.Private, StandardIds.Position, CoreSystemTypes.Int32, null);
  12712. members.Add(pField);
  12713. //Constructor
  12714. Parameter par = new Parameter(null, ParameterFlags.None, StandardIds.Value, tuple, null, null);
  12715. StatementList statements = new StatementList(4);
  12716. InstanceInitializer constr = CoreSystemTypes.Object.GetConstructor();
  12717. if (constr == null) { Debug.Fail(""); return enumerator; }
  12718. This thisParameter = new This(enumerator);
  12719. MethodCall mcall = new MethodCall(new MemberBinding(thisParameter, constr), new ExpressionList(0), NodeType.Call, CoreSystemTypes.Void);
  12720. statements.Add(new ExpressionStatement(mcall));
  12721. statements.Add(new AssignmentStatement(new MemberBinding(thisParameter, tField), par));
  12722. statements.Add(new AssignmentStatement(new MemberBinding(thisParameter, pField), Literal.Int32MinusOne));
  12723. statements.Add(new Return());
  12724. InstanceInitializer econs = new InstanceInitializer(enumerator, null, new ParameterList(par), new Block(statements));
  12725. econs.ThisParameter = thisParameter;
  12726. econs.Flags |= MethodFlags.Public;
  12727. members.Add(econs);
  12728. //get_Current
  12729. thisParameter = new This(enumerator);
  12730. statements = new StatementList(numDomains+1);
  12731. BlockList blocks = new BlockList(numDomains);
  12732. statements.Add(new SwitchInstruction(new MemberBinding(thisParameter, pField), blocks));
  12733. constr = SystemTypes.InvalidOperationException.GetConstructor();
  12734. if (constr == null) { Debug.Fail(""); return enumerator; }
  12735. statements.Add(new Throw(new Construct(new MemberBinding(null, constr), null)));
  12736. for (int i = 0; i < numDomains; i++){
  12737. Field f = (Field)tuple.members[i];
  12738. MemberBinding mb = new MemberBinding(new UnaryExpression(new MemberBinding(thisParameter, tField), NodeType.AddressOf), f);
  12739. Block b = new Block();
  12740. statements.Add(b);
  12741. blocks.Add(b);
  12742. if (f.Type == elementType || f.Type == null)
  12743. b.Statements = new StatementList(new Return(mb));
  12744. else{
  12745. TypeUnion tUnion = elementType as TypeUnion;
  12746. Debug.Assert(tUnion != null);
  12747. if (tUnion != null){
  12748. Method m = tUnion.GetImplicitCoercionFromMethod(f.Type);
  12749. if (m != null){
  12750. MethodCall mCall = new MethodCall(new MemberBinding(null, m), new ExpressionList(mb));
  12751. b.Statements = new StatementList(new Return(mCall));
  12752. }else{
  12753. TypeUnion eUnion = f.Type as TypeUnion;
  12754. if (eUnion != null){
  12755. Method getTagAsType = eUnion.GetMethod(StandardIds.GetTagAsType);
  12756. Method getValue = eUnion.GetMethod(StandardIds.GetValue);
  12757. Method fromObject = tUnion.GetMethod(StandardIds.FromObject, CoreSystemTypes.Object, CoreSystemTypes.Type);
  12758. if (getTagAsType == null || getValue == null || fromObject == null) {
  12759. Debug.Fail(""); return enumerator;
  12760. }
  12761. Local temp = new Local(Identifier.Empty, eUnion);
  12762. Expression tempAddr = new UnaryExpression(temp, NodeType.AddressOf);
  12763. StatementList stats = new StatementList(2);
  12764. stats.Add(new AssignmentStatement(temp, mb));
  12765. ExpressionList arguments = new ExpressionList(2);
  12766. arguments.Add(new MethodCall(new MemberBinding(tempAddr, getValue), null));
  12767. arguments.Add(new MethodCall(new MemberBinding(tempAddr, getTagAsType), null));
  12768. stats.Add(new Return(new MethodCall(new MemberBinding(null, fromObject), arguments)));
  12769. b.Statements = stats;
  12770. }else{
  12771. Debug.Assert(false);
  12772. }
  12773. }
  12774. }
  12775. }
  12776. }
  12777. Method getCurrent = new Method(enumerator, null, StandardIds.getCurrent, null, elementType, new Block(statements));
  12778. getCurrent.Flags = MethodFlags.Public|MethodFlags.Virtual|MethodFlags.NewSlot|MethodFlags.HideBySig|MethodFlags.SpecialName;
  12779. getCurrent.CallingConvention = CallingConventionFlags.HasThis;
  12780. getCurrent.ThisParameter = thisParameter;
  12781. members.Add(getCurrent);
  12782. //IEnumerator.GetCurrent
  12783. statements = new StatementList(1);
  12784. This ThisParameter = new This(enumerator);
  12785. MethodCall callGetCurrent = new MethodCall(new MemberBinding(ThisParameter, getCurrent), new ExpressionList(0), NodeType.Call, elementType);
  12786. MemberBinding etExpr = new MemberBinding(null, elementType);
  12787. statements.Add(new Return(new BinaryExpression(callGetCurrent, etExpr, NodeType.Box, CoreSystemTypes.Object)));
  12788. Method ieGetCurrent = new Method(enumerator, null, StandardIds.IEnumeratorGetCurrent, null, CoreSystemTypes.Object, new Block(statements));
  12789. ieGetCurrent.ThisParameter = ThisParameter;
  12790. ieGetCurrent.ImplementedInterfaceMethods = new MethodList(SystemTypes.IEnumerator.GetMethod(StandardIds.getCurrent));
  12791. ieGetCurrent.CallingConvention = CallingConventionFlags.HasThis;
  12792. ieGetCurrent.Flags = MethodFlags.Private|MethodFlags.Virtual|MethodFlags.SpecialName;
  12793. members.Add(ieGetCurrent);
  12794. //IEnumerator.Reset
  12795. statements = new StatementList(2);
  12796. ThisParameter = new This(enumerator);
  12797. statements.Add(new AssignmentStatement(new MemberBinding(ThisParameter, pField), Literal.Int32Zero));
  12798. statements.Add(new Return());
  12799. Method reset = new Method(enumerator, null, StandardIds.IEnumeratorReset, null, CoreSystemTypes.Void, new Block(statements));
  12800. reset.ThisParameter = ThisParameter;
  12801. reset.ImplementedInterfaceMethods = new MethodList(SystemTypes.IEnumerator.GetMethod(StandardIds.Reset));
  12802. reset.CallingConvention = CallingConventionFlags.HasThis;
  12803. reset.Flags = MethodFlags.Private|MethodFlags.Virtual|MethodFlags.SpecialName;
  12804. members.Add(reset);
  12805. //MoveNext
  12806. ThisParameter = new This(enumerator);
  12807. statements = new StatementList(5);
  12808. MemberBinding pos = new MemberBinding(ThisParameter, pField);
  12809. Expression comparison = new BinaryExpression(pos, new Literal(numDomains, CoreSystemTypes.Int32), NodeType.Lt);
  12810. Block returnTrue = new Block();
  12811. statements.Add(new AssignmentStatement(pos, new BinaryExpression(pos, Literal.Int32One, NodeType.Add)));
  12812. statements.Add(new Branch(comparison, returnTrue));
  12813. statements.Add(new Return(Literal.False));
  12814. statements.Add(returnTrue);
  12815. statements.Add(new Return(Literal.True));
  12816. Method moveNext = new Method(enumerator, null, StandardIds.MoveNext, null, CoreSystemTypes.Boolean, new Block(statements));
  12817. moveNext.Flags = MethodFlags.Public|MethodFlags.Virtual|MethodFlags.NewSlot|MethodFlags.HideBySig;
  12818. moveNext.CallingConvention = CallingConventionFlags.HasThis;
  12819. moveNext.ThisParameter = ThisParameter;
  12820. members.Add(moveNext);
  12821. //IDispose.Dispose
  12822. statements = new StatementList(1);
  12823. statements.Add(new Return());
  12824. Method dispose = new Method(enumerator, null, StandardIds.Dispose, null, CoreSystemTypes.Void, new Block(statements));
  12825. dispose.CallingConvention = CallingConventionFlags.HasThis;
  12826. dispose.Flags = MethodFlags.Public|MethodFlags.Virtual;
  12827. enumerator.Members.Add(dispose);
  12828. return enumerator;
  12829. }
  12830. }
  12831. public class TypeAlias : Struct{
  12832. protected TypeNode aliasedType;
  12833. public TypeNode AliasedTypeExpression;
  12834. public bool RequireExplicitCoercionFromUnderlyingType;
  12835. public TypeAlias()
  12836. : this(null, null){
  12837. }
  12838. internal TypeAlias(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle, bool requireExplicitCoercionFromUnderlyingType)
  12839. : base(provideNestedTypes, provideAttributes, provideMembers, handle) {
  12840. this.RequireExplicitCoercionFromUnderlyingType = requireExplicitCoercionFromUnderlyingType;
  12841. }
  12842. public TypeAlias(TypeNode aliasedType, Identifier name)
  12843. : base(){
  12844. this.NodeType = NodeType.TypeAlias;
  12845. this.AliasedType = aliasedType;
  12846. this.Name = name;
  12847. }
  12848. public TypeNode AliasedType{
  12849. get{
  12850. if (this.aliasedType == null){
  12851. Field f = this.GetField(StandardIds.Value);
  12852. if (f != null)
  12853. this.aliasedType = f.Type;
  12854. }
  12855. return this.aliasedType;
  12856. }
  12857. set{
  12858. this.aliasedType = value;
  12859. }
  12860. }
  12861. public virtual void ProvideMembers(){
  12862. if (this.AliasedType == null) return;
  12863. this.Interfaces = new InterfaceList(1);
  12864. if (this.RequireExplicitCoercionFromUnderlyingType)
  12865. this.Interfaces.Add(SystemTypes.TypeDefinition);
  12866. else
  12867. this.Interfaces.Add(SystemTypes.TypeAlias);
  12868. MemberList members = this.members;
  12869. if (members == null) members = this.members = new MemberList();
  12870. //Value field
  12871. Field valueField = new Field(this, null, FieldFlags.Private, StandardIds.Value, this.AliasedType, null);
  12872. members.Add(valueField);
  12873. //Implicit conversion from this type to underlying type
  12874. ParameterList parameters = new ParameterList(1);
  12875. Parameter valuePar = new Parameter(null, ParameterFlags.None, StandardIds.Value, this, null, null);
  12876. parameters.Add(valuePar);
  12877. Method toAliasedType = new Method(this, null, StandardIds.opImplicit, parameters, this.AliasedType, null);
  12878. toAliasedType.Flags = MethodFlags.Static|MethodFlags.SpecialName|MethodFlags.Public;
  12879. members.Add(toAliasedType);
  12880. StatementList statements = new StatementList(1);
  12881. statements.Add(new Return(new MemberBinding(new UnaryExpression(valuePar, NodeType.AddressOf), valueField)));
  12882. toAliasedType.Body = new Block(statements);
  12883. //Implicit or explicit conversion from underlying type to this type
  12884. Identifier opId = this.RequireExplicitCoercionFromUnderlyingType ? StandardIds.opExplicit : StandardIds.opImplicit;
  12885. parameters = new ParameterList(1);
  12886. parameters.Add(valuePar = new Parameter(null, ParameterFlags.None, StandardIds.Value, this.AliasedType, null, null));
  12887. Method fromAliasedType = new Method(this, null, opId, parameters, this, null);
  12888. fromAliasedType.Flags = MethodFlags.Static|MethodFlags.SpecialName|MethodFlags.Public;
  12889. members.Add(fromAliasedType);
  12890. statements = new StatementList(2);
  12891. Local loc = new Local(this);
  12892. statements.Add(new AssignmentStatement(new MemberBinding(new UnaryExpression(loc, NodeType.AddressOf), valueField), valuePar));
  12893. statements.Add(new Return(loc));
  12894. fromAliasedType.Body = new Block(statements);
  12895. this.AddCoercionWrappers(this.AliasedType.ExplicitCoercionMethods, StandardIds.opExplicit, fromAliasedType, toAliasedType);
  12896. this.AddCoercionWrappers(this.AliasedType.ImplicitCoercionMethods, StandardIds.opImplicit, fromAliasedType, toAliasedType);
  12897. }
  12898. private void AddCoercionWrappers(MemberList coercions, Identifier id, Method/*!*/ fromAliasedType, Method/*!*/ toAliasedType)
  12899. //^ requires this.members != null;
  12900. {
  12901. if (coercions == null) return;
  12902. MemberList members = this.members;
  12903. for (int i = 0, n = coercions.Count; i < n; i++){
  12904. Method coercion = coercions[i] as Method;
  12905. if (coercion == null || coercion.Parameters == null || coercion.Parameters.Count != 1) continue;
  12906. ParameterList parameters = new ParameterList(1);
  12907. Parameter valuePar = new Parameter(null, ParameterFlags.None, StandardIds.Value, null, null, null);
  12908. parameters.Add(valuePar);
  12909. Method m = new Method(this, null, id, parameters, null, null);
  12910. m.Flags = MethodFlags.Static|MethodFlags.SpecialName|MethodFlags.Public;
  12911. Expression arg = valuePar;
  12912. MethodCall call = new MethodCall(new MemberBinding(null, coercion), new ExpressionList(arg));
  12913. if (coercion.ReturnType == this.AliasedType){
  12914. m.ReturnType = this;
  12915. if (this.RequireExplicitCoercionFromUnderlyingType) m.Name = StandardIds.opExplicit;
  12916. valuePar.Type = coercion.Parameters[0].Type;
  12917. call = new MethodCall(new MemberBinding(null, fromAliasedType), new ExpressionList(call));
  12918. }else{
  12919. m.ReturnType = coercion.ReturnType;
  12920. valuePar.Type = this;
  12921. //^ assume call.Operands != null;
  12922. call.Operands[0] = new MethodCall(new MemberBinding(null, toAliasedType), new ExpressionList(arg));
  12923. }
  12924. m.Body = new Block(new StatementList(new Return(call)));
  12925. members.Add(m);
  12926. }
  12927. }
  12928. public override bool IsStructural{
  12929. get{return this.RequireExplicitCoercionFromUnderlyingType;}
  12930. }
  12931. protected TypeNodeList structuralElementTypes;
  12932. public override TypeNodeList StructuralElementTypes{
  12933. get{
  12934. TypeNodeList result = this.structuralElementTypes;
  12935. if (result != null) return result;
  12936. this.structuralElementTypes = result = new TypeNodeList(1);
  12937. result.Add(this.AliasedType);
  12938. return result;
  12939. }
  12940. }
  12941. public override bool IsStructurallyEquivalentTo(TypeNode type){
  12942. if (type == null) return false;
  12943. if (this == type) return true;
  12944. if (this.RequireExplicitCoercionFromUnderlyingType) return false;
  12945. TypeAlias t = type as TypeAlias;
  12946. if (t == null) return false;
  12947. if (t.RequireExplicitCoercionFromUnderlyingType) return false;
  12948. if (this.AliasedType == null || t.AliasedType == null) return false;
  12949. return this.AliasedType == t.AliasedType || this.AliasedType.IsStructurallyEquivalentTo(t.AliasedType);
  12950. }
  12951. }
  12952. public class TypeIntersection : Struct{
  12953. private TypeNodeList types; //sorted by UniqueKey
  12954. public TypeNodeList Types{
  12955. get{
  12956. if (this.types != null) return this.types;
  12957. if (this.ProvideTypeMembers != null) { MemberList mems = this.Members; if (mems != null) mems = null; }
  12958. return this.types;
  12959. }
  12960. set{
  12961. this.types = value;
  12962. }
  12963. }
  12964. private TypeIntersection(TypeNodeList types, Identifier name) {
  12965. this.NodeType = NodeType.TypeIntersection;
  12966. this.Flags = TypeFlags.Public|TypeFlags.Sealed;
  12967. this.Namespace = StandardIds.StructuralTypes;
  12968. this.Name = name;
  12969. this.Types = types;
  12970. int n = types == null ? 0 : types.Count;
  12971. InterfaceList ifaces = this.Interfaces = new InterfaceList(n+1);
  12972. ifaces.Add(SystemTypes.TypeIntersection);
  12973. if (types != null)
  12974. for (int i = 0; i < n; i++){
  12975. Interface iface = types[i] as Interface;
  12976. if (iface == null) continue;
  12977. ifaces.Add(iface);
  12978. }
  12979. this.isNormalized = true;
  12980. }
  12981. internal TypeIntersection(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  12982. : base(provideNestedTypes, provideAttributes, provideMembers, handle) {
  12983. this.NodeType = NodeType.TypeIntersection;
  12984. this.typeCode = ElementType.ValueType;
  12985. }
  12986. public static TypeIntersection For(TypeNodeList types, Module module) {
  12987. if (module == null) return null;
  12988. if (types != null && !TypeUnion.AreNormalized(types))
  12989. types = TypeUnion.Normalize(types);
  12990. TypeFlags visibility = TypeFlags.Public;
  12991. string name = TypeUnion.BuildName(types, "And", ref visibility);
  12992. Identifier tName = Identifier.For(name);
  12993. int tCount = 0;
  12994. TypeIntersection result = null;
  12995. TypeNode t = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, tName);
  12996. while (t != null){
  12997. //Mangled name is the same. But mangling is not unique, so check for equality.
  12998. TypeIntersection ti = t as TypeIntersection;
  12999. if (ti != null){
  13000. TypeNodeList ts = ti.Types;
  13001. int n = types == null ? 0 : types.Count;
  13002. bool goodMatch = ts != null && ts.Count == n;
  13003. for (int i = 0; goodMatch && i < n; i++) {
  13004. //^ assert types != null && ts != null;
  13005. goodMatch = types[i] == ts[i];
  13006. }
  13007. if (goodMatch) return ti;
  13008. }
  13009. //Mangle some more
  13010. tName = Identifier.For(name+(++tCount).ToString());
  13011. t = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, tName);
  13012. }
  13013. result = new TypeIntersection(types, tName);
  13014. result.DeclaringModule = module;
  13015. module.Types.Add(result);
  13016. module.StructurallyEquivalentType[tName.UniqueIdKey] = result;
  13017. return result;
  13018. }
  13019. public static TypeIntersection For(TypeNodeList types, TypeNode referringType) {
  13020. if (referringType == null) return null;
  13021. Module module = referringType.DeclaringModule;
  13022. if (module == null) return null;
  13023. if (types != null && !TypeUnion.AreNormalized(types))
  13024. types = TypeUnion.Normalize(types);
  13025. TypeFlags visibility = TypeFlags.Public;
  13026. string name = TypeUnion.BuildName(types, "And", ref visibility);
  13027. Identifier tName = Identifier.For(name);
  13028. int tCount = 0;
  13029. TypeIntersection result = null;
  13030. TypeNode t = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, tName);
  13031. while (t != null){
  13032. //Mangled name is the same. But mangling is not unique, so check for equality.
  13033. TypeIntersection ti = t as TypeIntersection;
  13034. if (ti != null){
  13035. TypeNodeList ts = ti.Types;
  13036. int n = types == null ? 0 : types.Count;
  13037. bool goodMatch = ts != null && ts.Count == n;
  13038. for (int i = 0; goodMatch && i < n; i++) {
  13039. //^ assert ts != null && types != null;
  13040. goodMatch = types[i] == ts[i];
  13041. }
  13042. if (goodMatch) return ti;
  13043. }
  13044. //Mangle some more
  13045. tName = Identifier.For(name+(++tCount).ToString());
  13046. t = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, tName);
  13047. }
  13048. result = new TypeIntersection(types, tName);
  13049. result.DeclaringModule = module;
  13050. switch (visibility){
  13051. case TypeFlags.NestedFamANDAssem:
  13052. case TypeFlags.NestedFamily:
  13053. case TypeFlags.NestedPrivate:
  13054. referringType.Members.Add(result);
  13055. result.DeclaringType = referringType;
  13056. result.Flags &= ~TypeFlags.VisibilityMask;
  13057. result.Flags |= TypeFlags.NestedPrivate;
  13058. break;
  13059. default:
  13060. module.Types.Add(result);
  13061. break;
  13062. }
  13063. module.StructurallyEquivalentType[tName.UniqueIdKey] = result;
  13064. return result;
  13065. }
  13066. public override bool IsAssignableTo(TypeNode targetType){
  13067. return targetType == this || targetType == CoreSystemTypes.Object;
  13068. }
  13069. public override bool IsStructural{
  13070. get{return true;}
  13071. }
  13072. protected TypeNodeList structuralElementTypes;
  13073. public override TypeNodeList StructuralElementTypes{
  13074. get{
  13075. TypeNodeList result = this.structuralElementTypes;
  13076. if (result != null) return result;
  13077. this.structuralElementTypes = result = new TypeNodeList(1);
  13078. TypeNodeList types = this.Types;
  13079. for (int i = 0, n = types == null ? 0 : types.Count; i < n; i++){
  13080. TypeNode t = types[i];
  13081. if (t == null) continue;
  13082. result.Add(t);
  13083. }
  13084. return result;
  13085. }
  13086. }
  13087. public override bool IsStructurallyEquivalentTo(TypeNode type){
  13088. if (type == null) return false;
  13089. if (this == type) return true;
  13090. TypeIntersection t = type as TypeIntersection;
  13091. if (t == null) return false;
  13092. return this.IsStructurallyEquivalentList(this.Types, t.Types);
  13093. }
  13094. private TrivialHashtable/*!*/ interfaceMethodFor = new TrivialHashtable();
  13095. public override MemberList Members{
  13096. get{
  13097. MemberList members = this.members;
  13098. if (members == null || this.membersBeingPopulated){
  13099. if (this.ProvideTypeMembers != null){
  13100. lock(this){
  13101. if (this.members != null) return this.members;
  13102. members = base.Members;
  13103. MemberList coercions = this.ExplicitCoercionMethods;
  13104. int n = coercions == null ? 0 : coercions.Count;
  13105. TypeNodeList typeList = this.Types = new TypeNodeList(n);
  13106. for (int i = 0; i < n; i++){
  13107. Method coercion = coercions[i] as Method;
  13108. if (coercion == null) continue;
  13109. typeList.Add(coercion.ReturnType);
  13110. }
  13111. }
  13112. return this.members;
  13113. }
  13114. members = this.Members = new MemberList();
  13115. //Value field
  13116. members.Add(new Field(this, null, FieldFlags.Private, StandardIds.Value, CoreSystemTypes.Object, null));
  13117. //FromObject
  13118. ParameterList parameters = new ParameterList(1);
  13119. parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.Value, CoreSystemTypes.Object, null, null));
  13120. Method m = new Method(this, null, StandardIds.FromObject, parameters, this, null);
  13121. m.Flags = MethodFlags.Static|MethodFlags.SpecialName|MethodFlags.Public;
  13122. members.Add(m);
  13123. //coercion operators
  13124. parameters = new ParameterList(1);
  13125. parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.Value, CoreSystemTypes.Object, null, null));
  13126. m = new Method(this, null, StandardIds.opExplicit, parameters, this, null);
  13127. m.Flags = MethodFlags.Static|MethodFlags.SpecialName|MethodFlags.Public;
  13128. members.Add(m);
  13129. parameters = new ParameterList(1);
  13130. parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.Value, this, null, null));
  13131. m = new Method(this, null, StandardIds.opImplicit, parameters, CoreSystemTypes.Object, null);
  13132. m.Flags = MethodFlags.Static|MethodFlags.SpecialName|MethodFlags.Public;
  13133. members.Add(m);
  13134. TypeNodeList types = this.Types;
  13135. for (int i = 0, n = types.Count; i < n; i++){
  13136. TypeNode t = types[i];
  13137. parameters = new ParameterList(1);
  13138. parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.Value, this, null, null));
  13139. m = new Method(this, null, StandardIds.opImplicit, parameters, t, null);
  13140. m.Flags = MethodFlags.Static|MethodFlags.SpecialName|MethodFlags.Public;
  13141. members.Add(m);
  13142. }
  13143. //Routines to forward interface calls to embedded object
  13144. InterfaceList ifaces = this.Interfaces;
  13145. if (ifaces != null){
  13146. for (int i = 0, n = ifaces.Count; i < n; i++){
  13147. Interface iface = ifaces[i];
  13148. if (iface == null) continue;
  13149. MemberList imembers = iface.Members;
  13150. if (imembers == null) continue;
  13151. for (int j = 0, k = imembers.Count; j < k; j++){
  13152. Method imeth = imembers[j] as Method;
  13153. if (imeth == null) continue;
  13154. if (imeth.IsStatic) continue;
  13155. Method meth = (Method)imeth.Clone();
  13156. meth.Flags &= ~MethodFlags.Abstract;
  13157. meth.DeclaringType = this;
  13158. members.Add(meth);
  13159. meth.Parameters = (imeth.Parameters == null ? null : imeth.Parameters.Clone());
  13160. for (int a = 0, b = meth.Parameters == null ? 0 : meth.Parameters.Count; a < b; a++){
  13161. Parameter par = meth.Parameters[a];
  13162. if (par == null) continue;
  13163. meth.Parameters[a] = par = (Parameter)par.Clone();
  13164. par.DeclaringMethod = meth;
  13165. }
  13166. this.interfaceMethodFor[meth.UniqueKey] = imeth;
  13167. }
  13168. }
  13169. }
  13170. this.ProvideBodiesForMethods();
  13171. }
  13172. return members;
  13173. }
  13174. set{
  13175. this.members = value;
  13176. }
  13177. }
  13178. private void ProvideBodiesForMethods()
  13179. //^ requires this.members != null;
  13180. {
  13181. MemberList members = this.members;
  13182. Field valueField = (Field)members[0];
  13183. //FromObject
  13184. Method fromObject = (Method)members[1];
  13185. StatementList statements = new StatementList(2);
  13186. Local resultLoc = new Local(Identifier.Empty, this);
  13187. Expression param = fromObject.Parameters[0];
  13188. statements.Add(new AssignmentStatement(new MemberBinding(new UnaryExpression(resultLoc, NodeType.AddressOf), valueField), param));
  13189. statements.Add(new Return(resultLoc));
  13190. fromObject.Body = new Block(statements);
  13191. //to coercion
  13192. Method toMethod = (Method)members[2];
  13193. statements = new StatementList(2);
  13194. resultLoc = new Local(Identifier.Empty, this);
  13195. param = toMethod.Parameters[0];
  13196. Expression castExpr = param;
  13197. TypeNodeList types = this.Types;
  13198. int n = types.Count;
  13199. for (int i = 0; i < n; i++){
  13200. TypeNode t = types[i];
  13201. castExpr = new BinaryExpression(castExpr, new Literal(t, CoreSystemTypes.Type), NodeType.Castclass);
  13202. }
  13203. statements.Add(new AssignmentStatement(new MemberBinding(new UnaryExpression(resultLoc, NodeType.AddressOf), valueField), castExpr));
  13204. statements.Add(new Return(resultLoc));
  13205. toMethod.Body = new Block(statements);
  13206. //from coercions
  13207. Method opImplicit = (Method)members[3];
  13208. opImplicit.Body = new Block(statements = new StatementList(1));
  13209. Expression val = new MemberBinding(new UnaryExpression(opImplicit.Parameters[0], NodeType.AddressOf), valueField);
  13210. statements.Add(new Return(val));
  13211. for (int i = 0; i < n; i++){
  13212. TypeNode t = types[i];
  13213. opImplicit = (Method)members[4+i];
  13214. opImplicit.Body = new Block(statements = new StatementList(1));
  13215. val = new MemberBinding(new UnaryExpression(opImplicit.Parameters[0], NodeType.AddressOf), valueField);
  13216. val = new BinaryExpression(val, new Literal(t, CoreSystemTypes.Type), NodeType.Castclass);
  13217. statements.Add(new Return(val));
  13218. }
  13219. //Routines to forward interface calls to embedded object
  13220. for (int i = 4+n, m = members.Count; i < m; i++){
  13221. Method meth = (Method)members[i];
  13222. Method imeth = (Method)this.interfaceMethodFor[meth.UniqueKey];
  13223. Interface iface = (Interface)imeth.DeclaringType;
  13224. statements = new StatementList(2);
  13225. ParameterList parameters = meth.Parameters;
  13226. int k = parameters == null ? 0 : parameters.Count;
  13227. ExpressionList arguments = new ExpressionList(k);
  13228. if (parameters != null)
  13229. for (int j = 0; j < k; j++) arguments.Add(parameters[j]);
  13230. Expression obj = new BinaryExpression(new MemberBinding(meth.ThisParameter, valueField), new Literal(iface, CoreSystemTypes.Type), NodeType.Castclass);
  13231. MethodCall mcall = new MethodCall(new MemberBinding(obj, imeth), arguments, NodeType.Callvirt);
  13232. mcall.Type = imeth.ReturnType;
  13233. statements.Add(new ExpressionStatement(mcall));
  13234. statements.Add(new Return());
  13235. meth.Body = new Block(statements);
  13236. }
  13237. }
  13238. }
  13239. public class TypeUnion : Struct{
  13240. private TypeNodeList types; //sorted by UniqueKey
  13241. public TypeNodeList Types{
  13242. get{
  13243. if (this.types != null) return this.types;
  13244. if (this.ProvideTypeMembers != null) { MemberList mems = this.Members; if (mems != null) mems = null; }
  13245. return this.types;
  13246. }
  13247. set{
  13248. this.types = value;
  13249. }
  13250. }
  13251. private TypeUnion(TypeNodeList types, Identifier tName){
  13252. this.NodeType = NodeType.TypeUnion;
  13253. this.Flags = TypeFlags.Public|TypeFlags.Sealed;
  13254. this.Namespace = StandardIds.StructuralTypes;
  13255. this.Name = tName;
  13256. this.Types = types;
  13257. this.Interfaces = new InterfaceList(SystemTypes.TypeUnion);
  13258. this.isNormalized = true;
  13259. }
  13260. internal TypeUnion(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  13261. : base(provideNestedTypes, provideAttributes, provideMembers, handle) {
  13262. this.NodeType = NodeType.TypeUnion;
  13263. this.typeCode = ElementType.ValueType;
  13264. }
  13265. internal static string/*!*/ BuildName(TypeNodeList types, string separator, ref TypeFlags visibility) {
  13266. int n = types == null ? 0 : types.Count;
  13267. if (n == 0) return "EmtpyUnion";
  13268. StringBuilder sb = new StringBuilder();
  13269. if (types != null)
  13270. for (int i = 0; i < n; i++){
  13271. TypeNode t = types[i];
  13272. if (t == null) continue;
  13273. visibility = TypeNode.GetVisibilityIntersection(visibility, t.Flags & TypeFlags.VisibilityMask);
  13274. sb.Append(t.Name.ToString());
  13275. if (i < n-1) sb.Append(separator);
  13276. }
  13277. return sb.ToString();
  13278. }
  13279. public static bool AreNormalized(TypeNodeList/*!*/ types) {
  13280. int id = 0;
  13281. for (int i = 0, n = types.Count; i < n; i++){
  13282. TypeNode type = types[i];
  13283. if (type == null) continue;
  13284. if (type.UniqueKey <= id || type is TypeUnion) return false;
  13285. id = type.UniqueKey;
  13286. }
  13287. return true;
  13288. }
  13289. public static TypeNodeList/*!*/ Normalize(TypeNodeList/*!*/ types) {
  13290. if (types.Count == 0) return types;
  13291. Hashtable ht = new Hashtable();
  13292. for (int i = 0, n = types.Count; i < n; i++){
  13293. TypeNode type = types[i];
  13294. if (type == null) continue; // error already reported.
  13295. TypeUnion tu = type as TypeUnion;
  13296. if (tu != null){
  13297. for (int ti = 0, tn = tu.Types.Count; ti < tn; ti++){
  13298. type = tu.Types[ti];
  13299. ht[type.UniqueKey] = type;
  13300. }
  13301. }else{
  13302. ht[type.UniqueKey] = type;
  13303. }
  13304. }
  13305. SortedList list = new SortedList(ht);
  13306. TypeNodeList result = new TypeNodeList(list.Count);
  13307. foreach (TypeNode t in list.Values)
  13308. result.Add(t);
  13309. return result;
  13310. }
  13311. public static TypeUnion For(TypeNodeList types, Module module) {
  13312. if (module == null) return null;
  13313. if (types != null && !TypeUnion.AreNormalized(types))
  13314. types = TypeUnion.Normalize(types);
  13315. TypeFlags visibility = TypeFlags.Public;
  13316. string name = TypeUnion.BuildName(types, "Or", ref visibility);
  13317. Identifier tName = Identifier.For(name);
  13318. int tCount = 0;
  13319. TypeUnion result = null;
  13320. TypeNode t = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, tName);
  13321. while (t != null){
  13322. //Mangled name is the same. But mangling is not unique, so check for equality.
  13323. TypeUnion tu = t as TypeUnion;
  13324. if (tu != null){
  13325. TypeNodeList ts = tu.Types;
  13326. int n = types == null ? 0 : types.Count;
  13327. bool goodMatch = ts != null && ts.Count == n;
  13328. for (int i = 0; goodMatch && i < n; i++) {
  13329. //^ assert types != null && ts != null;
  13330. goodMatch = types[i] == ts[i];
  13331. }
  13332. if (goodMatch) return tu;
  13333. }
  13334. //Mangle some more
  13335. tName = Identifier.For(name+(++tCount).ToString());
  13336. t = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, tName);
  13337. }
  13338. result = new TypeUnion(types, tName);
  13339. result.DeclaringModule = module;
  13340. module.Types.Add(result);
  13341. module.StructurallyEquivalentType[tName.UniqueIdKey] = result;
  13342. return result;
  13343. }
  13344. public static TypeUnion For(TypeNodeList/*!*/ types, TypeNode/*!*/ referringType) {
  13345. Module module = referringType.DeclaringModule;
  13346. if (module == null) return null;
  13347. if (!TypeUnion.AreNormalized(types))
  13348. types = TypeUnion.Normalize(types);
  13349. TypeFlags visibility = TypeFlags.Public;
  13350. string name = TypeUnion.BuildName(types, "Or", ref visibility);
  13351. Identifier tName = Identifier.For(name);
  13352. int tCount = 0;
  13353. TypeUnion result = null;
  13354. TypeNode t = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, tName);
  13355. while (t != null){
  13356. //Mangled name is the same. But mangling is not unique, so check for equality.
  13357. TypeUnion tu = t as TypeUnion;
  13358. if (tu != null){
  13359. TypeNodeList ts = tu.Types;
  13360. int n = types.Count;
  13361. bool goodMatch = ts != null && ts.Count == n;
  13362. for (int i = 0; goodMatch && i < n; i++) {
  13363. //^ assert ts != null;
  13364. goodMatch = types[i] == ts[i];
  13365. }
  13366. if (goodMatch) return tu;
  13367. }
  13368. //Mangle some more
  13369. tName = Identifier.For(name+(++tCount).ToString());
  13370. t = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, tName);
  13371. }
  13372. result = new TypeUnion(types, tName);
  13373. result.DeclaringModule = module;
  13374. switch (visibility){
  13375. case TypeFlags.NestedFamANDAssem:
  13376. case TypeFlags.NestedFamily:
  13377. case TypeFlags.NestedPrivate:
  13378. referringType.Members.Add(result);
  13379. result.DeclaringType = referringType;
  13380. result.Flags &= ~TypeFlags.VisibilityMask;
  13381. result.Flags |= TypeFlags.NestedPrivate;
  13382. break;
  13383. default:
  13384. module.Types.Add(result);
  13385. break;
  13386. }
  13387. module.StructurallyEquivalentType[tName.UniqueIdKey] = result;
  13388. return result;
  13389. }
  13390. public override bool IsAssignableTo(TypeNode targetType){
  13391. return targetType == this || targetType == CoreSystemTypes.Object;
  13392. }
  13393. public override bool IsStructural{
  13394. get{return true;}
  13395. }
  13396. public override bool IsStructurallyEquivalentTo(TypeNode type){
  13397. if (type == null) return false;
  13398. if (this == type) return true;
  13399. TypeUnion t = type as TypeUnion;
  13400. if (t == null) return false;
  13401. return this.IsStructurallyEquivalentList(this.Types, t.Types);
  13402. }
  13403. protected TypeNodeList structuralElementTypes;
  13404. public override TypeNodeList StructuralElementTypes{
  13405. get{
  13406. TypeNodeList result = this.structuralElementTypes;
  13407. if (result != null) return result;
  13408. this.structuralElementTypes = result = new TypeNodeList(1);
  13409. TypeNodeList types = this.Types;
  13410. for (int i = 0, n = types == null ? 0 : types.Count; i < n; i++){
  13411. TypeNode t = types[i];
  13412. if (t == null) continue;
  13413. result.Add(t);
  13414. }
  13415. return result;
  13416. }
  13417. }
  13418. protected TypeUnion unlabeledUnion = null;
  13419. public virtual TypeUnion UnlabeledUnion{
  13420. get{
  13421. TypeUnion result = this.unlabeledUnion;
  13422. if (result != null) return result;
  13423. if (this.Types == null) return this.unlabeledUnion = this;
  13424. TypeNodeList types = this.Types.Clone();
  13425. bool noChange = true;
  13426. for (int i = 0, n = types.Count; i < n; i++){
  13427. TupleType tup = types[i] as TupleType;
  13428. if (tup != null && tup.Members != null && tup.Members.Count == 3 && tup.Members[0] is Field){
  13429. types[i] = ((Field)tup.Members[0]).Type;
  13430. noChange = false;
  13431. }
  13432. }
  13433. if (noChange)
  13434. return this.unlabeledUnion = this;
  13435. else
  13436. return this.unlabeledUnion = new TypeUnion(types, Identifier.Empty);
  13437. }
  13438. }
  13439. public override MemberList Members{
  13440. get{
  13441. MemberList members = this.members;
  13442. if (members == null || this.membersBeingPopulated){
  13443. if (this.ProvideTypeMembers != null){
  13444. lock(this){
  13445. if (this.members != null) return this.members;
  13446. members = base.Members;
  13447. MemberList coercions = this.ExplicitCoercionMethods;
  13448. int n = coercions == null ? 0 : coercions.Count;
  13449. TypeNodeList typeList = this.Types = new TypeNodeList(n);
  13450. for (int i = 0; i < n; i++){
  13451. Method coercion = coercions[i] as Method;
  13452. if (coercion == null) continue;
  13453. typeList.Add(coercion.ReturnType);
  13454. }
  13455. return this.members;
  13456. }
  13457. }
  13458. members = this.Members = new MemberList();
  13459. //Value field
  13460. members.Add(new Field(this, null, FieldFlags.Private, StandardIds.Value, CoreSystemTypes.Object, null));
  13461. //Tag field
  13462. members.Add(new Field(this, null, FieldFlags.Private, StandardIds.Tag, CoreSystemTypes.UInt32, null));
  13463. //GetValue method (used to convert from subtype to supertype via FromObject on the superType)
  13464. ParameterList parameters = new ParameterList(0);
  13465. Method m = new Method(this, null, StandardIds.GetValue, parameters, CoreSystemTypes.Object, null);
  13466. m.Flags = MethodFlags.SpecialName|MethodFlags.Public; m.CallingConvention = CallingConventionFlags.HasThis;
  13467. members.Add(m);
  13468. //GetTag method (used in typeswitch)
  13469. parameters = new ParameterList(0);
  13470. m = new Method(this, null, StandardIds.GetTag, parameters, CoreSystemTypes.UInt32, null);
  13471. m.Flags = MethodFlags.SpecialName|MethodFlags.Public; m.CallingConvention = CallingConventionFlags.HasThis;
  13472. members.Add(m);
  13473. //GetTagAsType method (used to convert from subtype to supertype via FromObject on the superType)
  13474. parameters = new ParameterList(0);
  13475. m = new Method(this, null, StandardIds.GetTagAsType, parameters, CoreSystemTypes.Type, null);
  13476. m.Flags = MethodFlags.SpecialName|MethodFlags.Public; m.CallingConvention = CallingConventionFlags.HasThis;
  13477. members.Add(m);
  13478. //GetType
  13479. parameters = new ParameterList(0);
  13480. m = new Method(this, null, StandardIds.GetType, parameters, CoreSystemTypes.Type, null);
  13481. m.Flags = MethodFlags.Public; m.CallingConvention = CallingConventionFlags.HasThis;
  13482. members.Add(m);
  13483. //FromObject
  13484. parameters = new ParameterList(2);
  13485. parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.Value, CoreSystemTypes.Object, null, null));
  13486. parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.TagType, CoreSystemTypes.Type, null, null));
  13487. m = new Method(this, null, StandardIds.FromObject, parameters, this, null);
  13488. m.Flags = MethodFlags.Static|MethodFlags.SpecialName|MethodFlags.Public;
  13489. members.Add(m);
  13490. //coercion operators
  13491. TypeNodeList types = this.Types;
  13492. for (int i = 0, n = types.Count; i < n; i++){
  13493. TypeNode t = types[i];
  13494. parameters = new ParameterList(1);
  13495. parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.Value, t, null, null));
  13496. m = new Method(this, null, StandardIds.opImplicit, parameters, this, null);
  13497. m.Flags = MethodFlags.Static|MethodFlags.SpecialName|MethodFlags.Public;
  13498. members.Add(m);
  13499. parameters = new ParameterList(1);
  13500. parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.Value, this, null, null));
  13501. m = new Method(this, null, StandardIds.opExplicit, parameters, t, null);
  13502. m.Flags = MethodFlags.Static|MethodFlags.SpecialName|MethodFlags.Public;
  13503. members.Add(m);
  13504. }
  13505. this.ProvideBodiesForMethods();
  13506. }
  13507. return members;
  13508. }
  13509. set{
  13510. this.members = value;
  13511. }
  13512. }
  13513. public void ProvideBodiesForMethods(){
  13514. Method objectGetType = CoreSystemTypes.Object.GetMethod(StandardIds.GetType);
  13515. Method typeGetTypeFromHandle = (Method)CoreSystemTypes.Type.GetMembersNamed(Identifier.For("GetTypeFromHandle"))[0];
  13516. Method typeGetTypeHandle = (Method)CoreSystemTypes.Type.GetMembersNamed(Identifier.For("get_TypeHandle"))[0];
  13517. Method runtimeTypeHandleGetValue = (Method)CoreSystemTypes.RuntimeTypeHandle.GetMembersNamed(Identifier.For("get_Value"))[0];
  13518. if (objectGetType == null || typeGetTypeFromHandle == null || typeGetTypeHandle == null || runtimeTypeHandleGetValue == null) {
  13519. Debug.Fail(""); return;
  13520. }
  13521. MemberList members = this.members;
  13522. if (members == null) return;
  13523. Field valueField = (Field)members[0];
  13524. Field tagField = (Field)members[1];
  13525. //GetValue
  13526. Method getValueMethod = (Method)members[2];
  13527. StatementList statements = new StatementList(1);
  13528. statements.Add(new Return(new MemberBinding(getValueMethod.ThisParameter, valueField)));
  13529. getValueMethod.Body = new Block(statements);
  13530. //GetTag
  13531. Method getTagMethod = (Method)members[3];
  13532. statements = new StatementList(1);
  13533. statements.Add(new Return(new MemberBinding(getTagMethod.ThisParameter, tagField)));
  13534. getTagMethod.Body = new Block(statements);
  13535. //GetTagAsType
  13536. Method getTagAsTypeMethod = (Method)members[4];
  13537. TypeNodeList types = this.Types;
  13538. int n = types.Count;
  13539. Block returnBlock = new Block();
  13540. statements = new StatementList(n+4);
  13541. getTagAsTypeMethod.Body = new Block(statements);
  13542. BlockList targets = new BlockList(n);
  13543. SwitchInstruction sw = new SwitchInstruction(new MemberBinding(getTagAsTypeMethod.ThisParameter, tagField), targets);
  13544. statements.Add(sw);
  13545. //TODO: throw an exception
  13546. statements.Add(new ExpressionStatement(new UnaryExpression(new Literal(CoreSystemTypes.Object, CoreSystemTypes.Type), NodeType.Ldtoken)));
  13547. statements.Add(returnBlock);
  13548. for (int i = 0; i < n; i++){
  13549. TypeNode t = types[i];
  13550. StatementList ldToken = new StatementList(2);
  13551. ldToken.Add(new ExpressionStatement(new UnaryExpression(new Literal(t, CoreSystemTypes.Type), NodeType.Ldtoken)));
  13552. ldToken.Add(new Branch(null, returnBlock));
  13553. Block ldtokBlock = new Block(ldToken);
  13554. targets.Add(ldtokBlock);
  13555. statements.Add(ldtokBlock);
  13556. }
  13557. statements = returnBlock.Statements = new StatementList(1);
  13558. statements.Add(new Return(new MethodCall(new MemberBinding(null, typeGetTypeFromHandle), null)));
  13559. //GetType
  13560. Method getTypeMethod = (Method)members[5];
  13561. statements = new StatementList(4);
  13562. getTypeMethod.Body = new Block(statements);
  13563. MemberBinding mb = new MemberBinding(getTypeMethod.ThisParameter, valueField);
  13564. Local loc = new Local(CoreSystemTypes.Object);
  13565. statements.Add(new AssignmentStatement(loc, mb));
  13566. Block callGetTagAsType = new Block();
  13567. statements.Add(new Branch(new UnaryExpression(loc, NodeType.LogicalNot), callGetTagAsType));
  13568. statements.Add(new Return(new MethodCall(new MemberBinding(loc, objectGetType), null)));
  13569. statements.Add(callGetTagAsType);
  13570. statements.Add(new Return(new MethodCall(new MemberBinding(getTypeMethod.ThisParameter, getTagAsTypeMethod), null)));
  13571. //FromObject
  13572. Method fromObjectMethod = (Method)members[6];
  13573. fromObjectMethod.InitLocals = true;
  13574. statements = new StatementList(n+8); //TODO: get the right expression
  13575. fromObjectMethod.Body = new Block(statements);
  13576. MethodCall getTypeHandle = new MethodCall(new MemberBinding(fromObjectMethod.Parameters[1], typeGetTypeHandle), null, NodeType.Callvirt);
  13577. Local handle = new Local(Identifier.Empty, CoreSystemTypes.RuntimeTypeHandle);
  13578. statements.Add(new AssignmentStatement(handle, getTypeHandle));
  13579. MethodCall getValue = new MethodCall(new MemberBinding(new UnaryExpression(handle, NodeType.AddressOf), runtimeTypeHandleGetValue), null);
  13580. getValue.Type = CoreSystemTypes.UIntPtr;
  13581. statements.Add(new ExpressionStatement(getValue));
  13582. Local temp = new Local(Identifier.Empty, CoreSystemTypes.UInt32);
  13583. Local result = new Local(Identifier.Empty, this);
  13584. Expression dup = new Expression(NodeType.Dup);
  13585. Block next = new Block();
  13586. Block curr = new Block();
  13587. Block setTag = new Block();
  13588. for (int i = 0; i < n; i++){
  13589. TypeNode t = types[i];
  13590. StatementList stats = curr.Statements = new StatementList(4);
  13591. UnaryExpression ldtok = new UnaryExpression(new Literal(t, CoreSystemTypes.Type), NodeType.Ldtoken);
  13592. stats.Add(new AssignmentStatement(handle, ldtok));
  13593. getValue = new MethodCall(new MemberBinding(new UnaryExpression(handle, NodeType.AddressOf), runtimeTypeHandleGetValue), null);
  13594. Expression compare = new BinaryExpression(dup, getValue, NodeType.Eq);
  13595. stats.Add(new Branch(compare, next));
  13596. stats.Add(new AssignmentStatement(temp, new Literal(i, CoreSystemTypes.UInt32)));
  13597. if (i < n-1)
  13598. stats.Add(new Branch(null, setTag));
  13599. statements.Add(curr);
  13600. curr = next;
  13601. next = new Block();
  13602. }
  13603. statements.Add(curr);
  13604. statements.Add(setTag);
  13605. statements.Add(new ExpressionStatement(new UnaryExpression(null, NodeType.Pop)));
  13606. Expression resultAddr = new UnaryExpression(result, NodeType.AddressOf);
  13607. statements.Add(new AssignmentStatement(new MemberBinding(resultAddr, tagField), temp));
  13608. statements.Add(new AssignmentStatement(new MemberBinding(resultAddr, valueField), fromObjectMethod.Parameters[0]));
  13609. statements.Add(new Return(result));
  13610. for (int i = 0; i < n; i++){
  13611. TypeNode t = types[i];
  13612. if (t == null) continue;
  13613. bool isValueType = t.IsValueType;
  13614. MemberBinding tExpr = new MemberBinding(null, t);
  13615. Method opImplicit = (Method)members[7+i*2];
  13616. opImplicit.Body = new Block(statements = new StatementList(3));
  13617. statements.Add(new AssignmentStatement(new MemberBinding(resultAddr, tagField), new Literal(i, CoreSystemTypes.UInt32)));
  13618. Parameter p0 = opImplicit.Parameters[0];
  13619. p0.Type = t;
  13620. Expression val = p0;
  13621. if (isValueType) val = new BinaryExpression(val, tExpr, NodeType.Box, CoreSystemTypes.Object);
  13622. statements.Add(new AssignmentStatement(new MemberBinding(resultAddr, valueField), val));
  13623. statements.Add(new Return(result));
  13624. Method opExplicit = (Method)members[8+i*2];
  13625. opExplicit.ReturnType = t;
  13626. opExplicit.Body = new Block(statements = new StatementList(1));
  13627. Expression loadValue = new MemberBinding(new UnaryExpression(opExplicit.Parameters[0], NodeType.AddressOf), valueField);
  13628. if (isValueType)
  13629. val = new AddressDereference(new BinaryExpression(loadValue, tExpr, NodeType.Unbox), t);
  13630. else
  13631. val = new BinaryExpression(loadValue, tExpr, NodeType.Castclass);
  13632. statements.Add(new Return(val));
  13633. }
  13634. }
  13635. }
  13636. /// <summary>
  13637. /// Bundles a type with a boolean expression. The bundle is a subtype of the given type.
  13638. /// The class is a struct with a single private field of the given type and implicit coercions to and from the underlying type.
  13639. /// The to coercion checks that the constraint is satisfied and throws ArgumentOutOfRangeException if not.
  13640. /// </summary>
  13641. public class ConstrainedType : Struct{
  13642. protected TypeNode underlyingType;
  13643. public TypeNode UnderlyingTypeExpression;
  13644. public Expression Constraint;
  13645. public ConstrainedType(TypeNode/*!*/ underlyingType, Expression/*!*/ constraint) {
  13646. this.NodeType = NodeType.ConstrainedType;
  13647. this.underlyingType = underlyingType;
  13648. this.Flags = TypeFlags.Public|TypeFlags.Sealed|TypeFlags.SpecialName;
  13649. this.Constraint = constraint;
  13650. this.Namespace = StandardIds.StructuralTypes;
  13651. this.Name = Identifier.For("Constrained type:"+base.UniqueKey);
  13652. this.Interfaces = new InterfaceList(SystemTypes.ConstrainedType);
  13653. }
  13654. public ConstrainedType(TypeNode/*!*/ underlyingType, Expression/*!*/ constraint, TypeNode/*!*/ declaringType) {
  13655. this.NodeType = NodeType.ConstrainedType;
  13656. this.underlyingType = underlyingType;
  13657. this.Flags = TypeFlags.NestedPublic|TypeFlags.Sealed|TypeFlags.SpecialName;
  13658. this.Constraint = constraint;
  13659. this.Namespace = StandardIds.StructuralTypes;
  13660. this.Name = Identifier.For("Constrained type:"+base.UniqueKey);
  13661. this.Interfaces = new InterfaceList(SystemTypes.ConstrainedType);
  13662. this.DeclaringType = declaringType;
  13663. this.DeclaringModule = declaringType.DeclaringModule;
  13664. declaringType.Members.Add(this);
  13665. }
  13666. internal ConstrainedType(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
  13667. : base(provideNestedTypes, provideAttributes, provideMembers, handle) {
  13668. this.NodeType = NodeType.ConstrainedType;
  13669. this.typeCode = ElementType.ValueType;
  13670. }
  13671. public override bool IsStructural{
  13672. get{return true;}
  13673. }
  13674. protected TypeNodeList structuralElementTypes;
  13675. public override TypeNodeList StructuralElementTypes{
  13676. get{
  13677. TypeNodeList result = this.structuralElementTypes;
  13678. if (result != null) return result;
  13679. this.structuralElementTypes = result = new TypeNodeList(1);
  13680. result.Add(this.UnderlyingType);
  13681. return result;
  13682. }
  13683. }
  13684. public virtual void ProvideMembers(){
  13685. MemberList members = this.members = new MemberList();
  13686. //Value field
  13687. Field valueField = new Field(this, null, FieldFlags.Assembly, StandardIds.Value, this.underlyingType, null);
  13688. members.Add(valueField);
  13689. //Implicit conversion from this type to underlying type
  13690. ParameterList parameters = new ParameterList(1);
  13691. Parameter valuePar = new Parameter(null, ParameterFlags.None, StandardIds.Value, this, null, null);
  13692. parameters.Add(valuePar);
  13693. Method toUnderlying = new Method(this, null, StandardIds.opImplicit, parameters, this.underlyingType, null);
  13694. toUnderlying.Flags = MethodFlags.Static|MethodFlags.SpecialName|MethodFlags.Public;
  13695. members.Add(toUnderlying);
  13696. //Implicit conversion from underlying type to this type
  13697. parameters = new ParameterList(1);
  13698. parameters.Add(valuePar = new Parameter(null, ParameterFlags.None, StandardIds.Value, this.underlyingType, null, null));
  13699. Method fromUnderlying = new Method(this, null, StandardIds.opImplicit, parameters, this, null);
  13700. fromUnderlying.Flags = MethodFlags.Static|MethodFlags.SpecialName|MethodFlags.Public;
  13701. members.Add(fromUnderlying);
  13702. this.AddCoercionWrappers(this.UnderlyingType.ExplicitCoercionMethods, StandardIds.opExplicit, fromUnderlying, toUnderlying);
  13703. this.AddCoercionWrappers(this.UnderlyingType.ImplicitCoercionMethods, StandardIds.opImplicit, fromUnderlying, toUnderlying);
  13704. }
  13705. private void AddCoercionWrappers(MemberList/*!*/ coercions, Identifier/*!*/ id, Method/*!*/ fromUnderlying, Method/*!*/ toUnderlying) {
  13706. MemberList members = this.members;
  13707. for (int i = 0, n = coercions.Count; i < n; i++){
  13708. Method coercion = coercions[i] as Method;
  13709. if (coercion == null || coercion.Parameters == null || coercion.Parameters.Count != 1) continue;
  13710. ParameterList parameters = new ParameterList(1);
  13711. Parameter valuePar = new Parameter(null, ParameterFlags.None, StandardIds.Value, null, null, null);
  13712. parameters.Add(valuePar);
  13713. Method m = new Method(this, null, id, parameters, null, null);
  13714. m.Flags = MethodFlags.Static|MethodFlags.SpecialName|MethodFlags.Public;
  13715. Expression arg = valuePar;
  13716. MethodCall call = new MethodCall(new MemberBinding(null, coercion), new ExpressionList(arg));
  13717. if (coercion.ReturnType == this.UnderlyingType){
  13718. m.ReturnType = this;
  13719. valuePar.Type = coercion.Parameters[0].Type;
  13720. call = new MethodCall(new MemberBinding(null, fromUnderlying), new ExpressionList(call));
  13721. }else{
  13722. m.ReturnType = coercion.ReturnType;
  13723. valuePar.Type = this;
  13724. call.Operands[0] = new MethodCall(new MemberBinding(null, toUnderlying), new ExpressionList(arg));
  13725. }
  13726. m.Body = new Block(new StatementList(new Return(call)));
  13727. members.Add(m);
  13728. }
  13729. }
  13730. public void ProvideBodiesForMethods(){
  13731. MemberList members = this.members;
  13732. if (members == null) return;
  13733. Field valueField = (Field)members[0];
  13734. //Implicit conversion from this type to underlying type
  13735. Method toUnderlying = (Method)members[1];
  13736. Parameter valuePar = toUnderlying.Parameters[0];
  13737. StatementList statements = new StatementList(1);
  13738. statements.Add(new Return(new MemberBinding(new UnaryExpression(valuePar, NodeType.AddressOf), valueField)));
  13739. toUnderlying.Body = new Block(statements);
  13740. //Implicit conversion from underlying type to this type
  13741. Method fromUnderlying = (Method)members[2];
  13742. valuePar = fromUnderlying.Parameters[0];
  13743. statements = new StatementList(4);
  13744. fromUnderlying.Body = new Block(statements);
  13745. Block succeed = new Block();
  13746. Local temp = new Local(Identifier.Empty, this);
  13747. statements.Add(new Branch(this.Constraint, succeed));
  13748. InstanceInitializer constr = SystemTypes.ArgumentOutOfRangeException.GetConstructor();
  13749. if (constr == null) { Debug.Fail(""); return; }
  13750. MemberBinding argException = new MemberBinding(null, constr);
  13751. statements.Add(new Throw(new Construct(argException, null)));
  13752. statements.Add(succeed);
  13753. statements.Add(new AssignmentStatement(new MemberBinding(new UnaryExpression(temp, NodeType.AddressOf), valueField), valuePar));
  13754. statements.Add(new Return(temp));
  13755. }
  13756. public TypeNode UnderlyingType{
  13757. get{
  13758. TypeNode underlyingType = this.underlyingType;
  13759. if (underlyingType == null){
  13760. Field f = this.GetField(StandardIds.Value);
  13761. if (f != null)
  13762. this.underlyingType = underlyingType = f.Type;
  13763. }
  13764. return underlyingType;
  13765. }
  13766. set{
  13767. this.underlyingType = value;
  13768. }
  13769. }
  13770. }
  13771. #endif
  13772. public abstract class TypeModifier : TypeNode{
  13773. private TypeNode/*!*/ modifier;
  13774. private TypeNode/*!*/ modifiedType;
  13775. #if !MinimalReader
  13776. public TypeNode ModifierExpression;
  13777. public TypeNode ModifiedTypeExpression;
  13778. #endif
  13779. internal TypeModifier(NodeType type, TypeNode/*!*/ modifier, TypeNode/*!*/ modified)
  13780. : base(type){
  13781. this.modifier = modifier;
  13782. this.modifiedType = modified;
  13783. this.DeclaringModule = modified.DeclaringModule;
  13784. this.Namespace = modified.Namespace;
  13785. if (type == NodeType.OptionalModifier){
  13786. this.typeCode = ElementType.OptionalModifier;
  13787. this.Name = Identifier.For("optional("+modifier.Name+") "+modified.Name);
  13788. this.fullName = "optional("+modifier.FullName+") "+modified.FullName;
  13789. }else{
  13790. this.typeCode = ElementType.RequiredModifier;
  13791. this.Name = Identifier.For("required("+modifier.Name+") "+modified.Name);
  13792. this.fullName = "required("+modifier.FullName+") "+modified.FullName;
  13793. }
  13794. this.Flags = modified.Flags;
  13795. }
  13796. public TypeNode/*!*/ Modifier {
  13797. get{return this.modifier;}
  13798. set{this.modifier = value;}
  13799. }
  13800. public TypeNode/*!*/ ModifiedType {
  13801. get{return this.modifiedType;}
  13802. set{this.modifiedType = value;}
  13803. }
  13804. public override Node/*!*/ Clone(){
  13805. Debug.Assert(false);
  13806. return base.Clone();
  13807. }
  13808. public override string GetFullUnmangledNameWithoutTypeParameters() {
  13809. return this.ModifiedType.GetFullUnmangledNameWithoutTypeParameters();
  13810. }
  13811. public override string GetFullUnmangledNameWithTypeParameters() {
  13812. return this.ModifiedType.GetFullUnmangledNameWithTypeParameters();
  13813. }
  13814. public override string/*!*/ GetUnmangledNameWithoutTypeParameters() {
  13815. return this.ModifiedType.GetUnmangledNameWithoutTypeParameters();
  13816. }
  13817. public override bool IsUnmanaged {
  13818. get{return this.ModifiedType.IsUnmanaged;}
  13819. }
  13820. public override bool IsStructural
  13821. {
  13822. get{return true;}
  13823. }
  13824. public override bool IsStructurallyEquivalentTo(TypeNode type){
  13825. if (type == null) return false;
  13826. if (this == type) return true;
  13827. if (this.NodeType != type.NodeType) return false;
  13828. TypeModifier t = type as TypeModifier;
  13829. if (t == null){Debug.Assert(false); return false;}
  13830. if (this.Modifier != t.Modifier && (this.Modifier == null || !this.Modifier.IsStructurallyEquivalentTo(t.Modifier)))
  13831. return false;
  13832. if (this.ModifiedType != t.ModifiedType && (this.ModifiedType == null || !this.ModifiedType.IsStructurallyEquivalentTo(t.ModifiedType)))
  13833. return false;
  13834. return true;
  13835. }
  13836. public override bool IsValueType {
  13837. get {
  13838. return this.ModifiedType.IsValueType;
  13839. }
  13840. }
  13841. public override bool IsPointerType {
  13842. get {
  13843. return this.ModifiedType.IsPointerType;
  13844. }
  13845. }
  13846. #if ExtendedRuntime
  13847. public override bool IsPointerFree
  13848. {
  13849. get { return this.ModifiedType.IsPointerFree; }
  13850. }
  13851. public override bool IsReferenceType
  13852. {
  13853. get {
  13854. return this.ModifiedType.IsReferenceType;
  13855. }
  13856. }
  13857. #endif
  13858. public override bool IsTemplateParameter {
  13859. get {
  13860. return this.ModifiedType.IsTemplateParameter;
  13861. }
  13862. }
  13863. protected TypeNodeList structuralElementTypes;
  13864. public override TypeNodeList StructuralElementTypes{
  13865. get{
  13866. TypeNodeList result = this.structuralElementTypes;
  13867. if (result != null) return result;
  13868. this.structuralElementTypes = result = new TypeNodeList(2);
  13869. result.Add(this.ModifiedType);
  13870. result.Add(this.Modifier);
  13871. return result;
  13872. }
  13873. }
  13874. #if FxCop
  13875. internal override void GetName(TypeFormat options, StringBuilder name)
  13876. {
  13877. if (options.ShowTypeModifiers)
  13878. {
  13879. base.GetName(options, name);
  13880. return;
  13881. }
  13882. this.modifiedType.GetName(options, name);
  13883. }
  13884. #endif
  13885. }
  13886. public class OptionalModifier : TypeModifier{
  13887. internal OptionalModifier(TypeNode/*!*/ modifier, TypeNode/*!*/ modified)
  13888. : base(NodeType.OptionalModifier, modifier, modified){
  13889. }
  13890. public static OptionalModifier For(TypeNode modifier, TypeNode modified) {
  13891. if (modified == null || modifier == null) return null;
  13892. return (OptionalModifier)modified.GetModified(modifier, true);
  13893. }
  13894. #if !NoXml
  13895. internal override void AppendDocumentIdMangledName(StringBuilder/*!*/ sb, TypeNodeList methodTypeParameters, TypeNodeList typeParameters) {
  13896. this.ModifiedType.AppendDocumentIdMangledName(sb, methodTypeParameters, typeParameters);
  13897. sb.Append('!');
  13898. this.Modifier.AppendDocumentIdMangledName(sb, methodTypeParameters, typeParameters);
  13899. }
  13900. #endif
  13901. }
  13902. public class RequiredModifier : TypeModifier{
  13903. internal RequiredModifier(TypeNode/*!*/ modifier, TypeNode/*!*/ modified)
  13904. : base(NodeType.RequiredModifier, modifier, modified){
  13905. }
  13906. public static RequiredModifier/*!*/ For(TypeNode/*!*/ modifier, TypeNode/*!*/ modified) {
  13907. return (RequiredModifier)modified.GetModified(modifier, false);
  13908. }
  13909. #if !NoXml
  13910. internal override void AppendDocumentIdMangledName(StringBuilder/*!*/ sb, TypeNodeList methodTypeParameters, TypeNodeList typeParameters) {
  13911. this.ModifiedType.AppendDocumentIdMangledName(sb, methodTypeParameters, typeParameters);
  13912. sb.Append('|');
  13913. this.Modifier.AppendDocumentIdMangledName(sb, methodTypeParameters, typeParameters);
  13914. }
  13915. #endif
  13916. }
  13917. #if !MinimalReader
  13918. public class OptionalModifierTypeExpression : TypeNode, ISymbolicTypeReference{
  13919. public TypeNode ModifiedType;
  13920. public TypeNode Modifier;
  13921. public OptionalModifierTypeExpression(TypeNode elementType, TypeNode modifier)
  13922. : base(NodeType.OptionalModifierTypeExpression){
  13923. this.ModifiedType = elementType;
  13924. this.Modifier = modifier;
  13925. }
  13926. public OptionalModifierTypeExpression(TypeNode elementType, TypeNode modifier, SourceContext sctx)
  13927. : this(elementType, modifier){
  13928. this.SourceContext = sctx;
  13929. }
  13930. /// <summary>
  13931. /// Only needed because IsUnmanaged test is performed in the Looker rather than checker. Once the test
  13932. /// is moved, this code can be removed.
  13933. /// </summary>
  13934. public override bool IsUnmanaged {
  13935. get {
  13936. return this.ModifiedType == null ? false : this.ModifiedType.IsUnmanaged;
  13937. }
  13938. }
  13939. }
  13940. public class RequiredModifierTypeExpression : TypeNode, ISymbolicTypeReference{
  13941. public TypeNode ModifiedType;
  13942. public TypeNode Modifier;
  13943. public RequiredModifierTypeExpression(TypeNode elementType, TypeNode modifier)
  13944. : base(NodeType.RequiredModifierTypeExpression){
  13945. this.ModifiedType = elementType;
  13946. this.Modifier = modifier;
  13947. }
  13948. public RequiredModifierTypeExpression(TypeNode elementType, TypeNode modifier, SourceContext sctx)
  13949. : this(elementType, modifier){
  13950. this.SourceContext = sctx;
  13951. }
  13952. /// <summary>
  13953. /// Can be removed once the Unmanaged check moves from Looker to Checker.
  13954. /// </summary>
  13955. public override bool IsUnmanaged {
  13956. get {
  13957. return this.ModifiedType == null ? false : this.ModifiedType.IsUnmanaged;
  13958. }
  13959. }
  13960. }
  13961. #endif
  13962. public class FunctionPointer : TypeNode{
  13963. internal FunctionPointer(TypeNodeList parameterTypes, TypeNode/*!*/ returnType, Identifier name)
  13964. : base(NodeType.FunctionPointer){
  13965. this.Name = name;
  13966. this.Namespace = returnType.Namespace;
  13967. this.parameterTypes = parameterTypes;
  13968. this.returnType = returnType;
  13969. this.typeCode = ElementType.FunctionPointer;
  13970. this.varArgStart = int.MaxValue;
  13971. }
  13972. private CallingConventionFlags callingConvention;
  13973. public CallingConventionFlags CallingConvention{
  13974. get{return this.callingConvention;}
  13975. set{this.callingConvention = value;}
  13976. }
  13977. private TypeNodeList parameterTypes;
  13978. public TypeNodeList ParameterTypes{
  13979. get{return this.parameterTypes;}
  13980. set{this.parameterTypes = value;}
  13981. }
  13982. private TypeNode returnType;
  13983. public TypeNode ReturnType{
  13984. get{return this.returnType;}
  13985. set{this.returnType = value;}
  13986. }
  13987. private int varArgStart;
  13988. public int VarArgStart{
  13989. get{return this.varArgStart;}
  13990. set{this.varArgStart = value;}
  13991. }
  13992. public override bool IsStatic{
  13993. get{return (this.CallingConvention & CallingConventionFlags.HasThis) == 0;}
  13994. }
  13995. public override bool IsStructural{
  13996. get{return true;}
  13997. }
  13998. protected TypeNodeList structuralElementTypes;
  13999. public override TypeNodeList StructuralElementTypes{
  14000. get{
  14001. TypeNodeList result = this.structuralElementTypes;
  14002. if (result != null) return result;
  14003. this.structuralElementTypes = result = new TypeNodeList();
  14004. result.Add(this.ReturnType);
  14005. TypeNodeList ptypes = this.ParameterTypes;
  14006. for (int i = 0, n = ptypes == null ? 0 : ptypes.Count; i < n; i++){
  14007. TypeNode ptype = ptypes[i];
  14008. if (ptype == null) continue;
  14009. result.Add(ptype);
  14010. }
  14011. return result;
  14012. }
  14013. }
  14014. public override bool IsStructurallyEquivalentTo(TypeNode type){
  14015. if (type == null) return false;
  14016. if (this == type) return true;
  14017. FunctionPointer t = type as FunctionPointer;
  14018. if (t == null) return false;
  14019. if (this.Flags != t.Flags || this.CallingConvention != t.CallingConvention || this.VarArgStart != t.VarArgStart) return false;
  14020. if (this.ReturnType == null || t.ReturnType == null) return false;
  14021. if (this.ReturnType != t.ReturnType && !this.ReturnType.IsStructurallyEquivalentTo(t.ReturnType)) return false;
  14022. return this.IsStructurallyEquivalentList(this.ParameterTypes, t.ParameterTypes);
  14023. }
  14024. public static FunctionPointer/*!*/ For(TypeNodeList/*!*/ parameterTypes, TypeNode/*!*/ returnType) {
  14025. Module mod = returnType.DeclaringModule;
  14026. if (mod == null) { Debug.Fail(""); mod = new Module(); }
  14027. StringBuilder sb = new StringBuilder("function pointer ");
  14028. sb.Append(returnType.FullName);
  14029. sb.Append('(');
  14030. for (int i = 0, n = parameterTypes == null ? 0 : parameterTypes.Count; i < n; i++){
  14031. TypeNode type = parameterTypes[i];
  14032. if (type == null) continue;
  14033. if (i != 0) sb.Append(',');
  14034. sb.Append(type.FullName);
  14035. }
  14036. sb.Append(')');
  14037. Identifier name = Identifier.For(sb.ToString());
  14038. TypeNode t = mod.GetStructurallyEquivalentType(returnType.Namespace, name);
  14039. int counter = 1;
  14040. while (t != null){
  14041. FunctionPointer fp = t as FunctionPointer;
  14042. if (fp != null){
  14043. if (fp.ReturnType == returnType && FunctionPointer.ParameterTypesAreEquivalent(fp.ParameterTypes, parameterTypes))
  14044. return fp;
  14045. }
  14046. name = Identifier.For(name.ToString()+counter++);
  14047. t = mod.GetStructurallyEquivalentType(returnType.Namespace, name);
  14048. }
  14049. FunctionPointer result = t as FunctionPointer;
  14050. if (result == null){
  14051. result = new FunctionPointer(parameterTypes, returnType, name);
  14052. result.DeclaringModule = mod;
  14053. mod.StructurallyEquivalentType[name.UniqueIdKey] = result;
  14054. }
  14055. return result;
  14056. }
  14057. private static bool ParameterTypesAreEquivalent(TypeNodeList list1, TypeNodeList list2){
  14058. if (list1 == null || list2 == null) return list1 == list2;
  14059. int n = list1.Count;
  14060. if (n != list2.Count) return false;
  14061. for (int i = 0; i < n; i++)
  14062. if (list1[i] != list2[i]) return false;
  14063. return true;
  14064. }
  14065. }
  14066. public interface ISymbolicTypeReference{
  14067. }
  14068. #if !MinimalReader
  14069. public class ArrayTypeExpression : ArrayType, ISymbolicTypeReference{
  14070. //TODO: add expressions for elementType, rank, sizes and lowerbounds
  14071. public bool LowerBoundIsUnknown;
  14072. public ArrayTypeExpression()
  14073. : base(){
  14074. this.NodeType = NodeType.ArrayTypeExpression;
  14075. }
  14076. public ArrayTypeExpression(TypeNode/*!*/ elementType, int rank)
  14077. : base(elementType, rank){
  14078. this.NodeType = NodeType.ArrayTypeExpression;
  14079. }
  14080. public ArrayTypeExpression(TypeNode/*!*/ elementType, int rank, int[] sizes)
  14081. : base(elementType, rank, sizes){
  14082. this.NodeType = NodeType.ArrayTypeExpression;
  14083. }
  14084. public ArrayTypeExpression(TypeNode/*!*/ elementType, int rank, int[] sizes, int[] lowerBounds)
  14085. : base(elementType, rank, sizes, sizes){
  14086. this.NodeType = NodeType.ArrayTypeExpression;
  14087. }
  14088. public ArrayTypeExpression(TypeNode/*!*/ elementType, int rank, SourceContext sctx)
  14089. : base(elementType, rank){
  14090. this.NodeType = NodeType.ArrayTypeExpression;
  14091. this.SourceContext = sctx;
  14092. }
  14093. public ArrayTypeExpression(TypeNode/*!*/ elementType, int rank, int[] sizes, SourceContext sctx)
  14094. : base(elementType, rank, sizes){
  14095. this.NodeType = NodeType.ArrayTypeExpression;
  14096. this.SourceContext = sctx;
  14097. }
  14098. public ArrayTypeExpression(TypeNode/*!*/ elementType, int rank, int[] sizes, int[] lowerBounds, SourceContext sctx)
  14099. : base(elementType, rank, sizes, sizes){
  14100. this.NodeType = NodeType.ArrayTypeExpression;
  14101. this.SourceContext = sctx;
  14102. }
  14103. }
  14104. public class ClassExpression : Class, ISymbolicTypeReference{
  14105. public Expression Expression;
  14106. public ClassExpression(Expression expression){
  14107. this.NodeType = NodeType.ClassExpression;
  14108. this.Expression = expression;
  14109. }
  14110. public ClassExpression(Expression expression, TypeNodeList templateArguments){
  14111. this.NodeType = NodeType.ClassExpression;
  14112. this.Expression = expression;
  14113. this.TemplateArguments = templateArguments;
  14114. if (templateArguments != null) this.TemplateArgumentExpressions = templateArguments.Clone();
  14115. }
  14116. public ClassExpression(Expression expression, SourceContext sctx){
  14117. this.NodeType = NodeType.ClassExpression;
  14118. this.Expression = expression;
  14119. this.SourceContext = sctx;
  14120. }
  14121. public ClassExpression(Expression expression, TypeNodeList templateArguments, SourceContext sctx) {
  14122. this.NodeType = NodeType.ClassExpression;
  14123. this.Expression = expression;
  14124. this.TemplateArguments = this.TemplateArgumentExpressions = templateArguments;
  14125. if (templateArguments != null) this.TemplateArgumentExpressions = templateArguments.Clone();
  14126. this.SourceContext = sctx;
  14127. }
  14128. }
  14129. #endif
  14130. public class InterfaceExpression : Interface, ISymbolicTypeReference{
  14131. private Expression expression;
  14132. public InterfaceExpression(Expression expression)
  14133. : base(null){
  14134. this.NodeType = NodeType.InterfaceExpression;
  14135. this.Expression = expression;
  14136. }
  14137. #if !MinimalReader
  14138. public InterfaceExpression(Expression expression, SourceContext sctx)
  14139. : base(null){
  14140. this.NodeType = NodeType.InterfaceExpression;
  14141. this.Expression = expression;
  14142. this.SourceContext = sctx;
  14143. }
  14144. #endif
  14145. public Expression Expression{
  14146. get{return this.expression;}
  14147. set{this.expression = value;}
  14148. }
  14149. }
  14150. #if !MinimalReader
  14151. public class FlexArrayTypeExpression : TypeNode, ISymbolicTypeReference{
  14152. public TypeNode ElementType;
  14153. public FlexArrayTypeExpression(TypeNode elementType)
  14154. : base(NodeType.FlexArrayTypeExpression){
  14155. this.ElementType = elementType;
  14156. }
  14157. public FlexArrayTypeExpression(TypeNode elementType, SourceContext sctx)
  14158. : base(NodeType.FlexArrayTypeExpression){
  14159. this.ElementType = elementType;
  14160. this.SourceContext = sctx;
  14161. }
  14162. }
  14163. public class FunctionTypeExpression : TypeNode, ISymbolicTypeReference{
  14164. public ParameterList Parameters;
  14165. public TypeNode ReturnType;
  14166. public FunctionTypeExpression(TypeNode returnType, ParameterList parameters)
  14167. : base(NodeType.FunctionTypeExpression){
  14168. this.ReturnType = returnType;
  14169. this.Parameters = parameters;
  14170. }
  14171. public FunctionTypeExpression(TypeNode returnType, ParameterList parameters, SourceContext sctx)
  14172. : base(NodeType.FunctionTypeExpression){
  14173. this.ReturnType = returnType;
  14174. this.Parameters = parameters;
  14175. this.SourceContext = sctx;
  14176. }
  14177. }
  14178. public class PointerTypeExpression : Pointer, ISymbolicTypeReference{
  14179. public PointerTypeExpression(TypeNode/*!*/ elementType)
  14180. : base(elementType){
  14181. this.NodeType = NodeType.PointerTypeExpression;
  14182. }
  14183. public PointerTypeExpression(TypeNode/*!*/ elementType, SourceContext sctx)
  14184. : base(elementType){
  14185. this.NodeType = NodeType.PointerTypeExpression;
  14186. this.SourceContext = sctx;
  14187. }
  14188. /// <summary>
  14189. /// This is only needed because the Unmanaged test is done in the Looker rather than the checker.
  14190. /// (Once the check moves, this can be removed).
  14191. /// </summary>
  14192. public override bool IsUnmanaged {
  14193. get {
  14194. return true;
  14195. }
  14196. }
  14197. }
  14198. public class ReferenceTypeExpression : Reference, ISymbolicTypeReference{
  14199. public ReferenceTypeExpression(TypeNode/*!*/ elementType)
  14200. : base(elementType){
  14201. this.NodeType = NodeType.ReferenceTypeExpression;
  14202. }
  14203. public ReferenceTypeExpression(TypeNode/*!*/ elementType, SourceContext sctx)
  14204. : base(elementType){
  14205. this.NodeType = NodeType.ReferenceTypeExpression;
  14206. this.SourceContext = sctx;
  14207. }
  14208. }
  14209. public class StreamTypeExpression : TypeNode, ISymbolicTypeReference{
  14210. public TypeNode ElementType;
  14211. public StreamTypeExpression(TypeNode elementType)
  14212. : base(NodeType.StreamTypeExpression){
  14213. this.ElementType = elementType;
  14214. }
  14215. public StreamTypeExpression(TypeNode elementType, SourceContext sctx)
  14216. : base(NodeType.StreamTypeExpression){
  14217. this.ElementType = elementType;
  14218. this.SourceContext = sctx;
  14219. }
  14220. }
  14221. public class NonEmptyStreamTypeExpression : TypeNode, ISymbolicTypeReference{
  14222. public TypeNode ElementType;
  14223. public NonEmptyStreamTypeExpression(TypeNode elementType)
  14224. : base(NodeType.NonEmptyStreamTypeExpression){
  14225. this.ElementType = elementType;
  14226. }
  14227. public NonEmptyStreamTypeExpression(TypeNode elementType, SourceContext sctx)
  14228. : base(NodeType.NonEmptyStreamTypeExpression){
  14229. this.ElementType = elementType;
  14230. this.SourceContext = sctx;
  14231. }
  14232. }
  14233. public class BoxedTypeExpression : TypeNode, ISymbolicTypeReference{
  14234. public TypeNode ElementType;
  14235. public BoxedTypeExpression(TypeNode elementType)
  14236. : base(NodeType.BoxedTypeExpression){
  14237. this.ElementType = elementType;
  14238. }
  14239. public BoxedTypeExpression(TypeNode elementType, SourceContext sctx)
  14240. : base(NodeType.BoxedTypeExpression){
  14241. this.ElementType = elementType;
  14242. this.SourceContext = sctx;
  14243. }
  14244. }
  14245. public class InvariantTypeExpression : TypeNode, ISymbolicTypeReference{
  14246. public TypeNode ElementType;
  14247. public InvariantTypeExpression(TypeNode elementType)
  14248. : base(NodeType.InvariantTypeExpression){
  14249. this.ElementType = elementType;
  14250. }
  14251. public InvariantTypeExpression(TypeNode elementType, SourceContext sctx)
  14252. : base(NodeType.InvariantTypeExpression){
  14253. this.ElementType = elementType;
  14254. this.SourceContext = sctx;
  14255. }
  14256. }
  14257. public class NonNullTypeExpression : TypeNode, ISymbolicTypeReference{
  14258. public TypeNode ElementType;
  14259. public NonNullTypeExpression(TypeNode elementType)
  14260. : base(NodeType.NonNullTypeExpression){
  14261. this.ElementType = elementType;
  14262. }
  14263. public NonNullTypeExpression(TypeNode elementType, SourceContext sctx)
  14264. : base(NodeType.NonNullTypeExpression){
  14265. this.ElementType = elementType;
  14266. this.SourceContext = sctx;
  14267. }
  14268. }
  14269. public class NonNullableTypeExpression : TypeNode, ISymbolicTypeReference{
  14270. public TypeNode ElementType;
  14271. public NonNullableTypeExpression(TypeNode elementType)
  14272. : base(NodeType.NonNullableTypeExpression){
  14273. this.ElementType = elementType;
  14274. }
  14275. public NonNullableTypeExpression(TypeNode elementType, SourceContext sctx)
  14276. : base(NodeType.NonNullableTypeExpression){
  14277. this.ElementType = elementType;
  14278. this.SourceContext = sctx;
  14279. }
  14280. }
  14281. public class NullableTypeExpression : TypeNode, ISymbolicTypeReference{
  14282. public TypeNode ElementType;
  14283. public NullableTypeExpression(TypeNode elementType)
  14284. : base(NodeType.NullableTypeExpression){
  14285. this.ElementType = elementType;
  14286. }
  14287. public NullableTypeExpression(TypeNode elementType, SourceContext sctx)
  14288. : base(NodeType.NullableTypeExpression){
  14289. this.ElementType = elementType;
  14290. this.SourceContext = sctx;
  14291. }
  14292. }
  14293. public class TupleTypeExpression : TypeNode, ISymbolicTypeReference{
  14294. public FieldList Domains;
  14295. public TupleTypeExpression(FieldList domains)
  14296. : base(NodeType.TupleTypeExpression){
  14297. this.Domains = domains;
  14298. }
  14299. public TupleTypeExpression(FieldList domains, SourceContext sctx)
  14300. : base(NodeType.TupleTypeExpression){
  14301. this.Domains = domains;
  14302. this.SourceContext = sctx;
  14303. }
  14304. }
  14305. public class TypeIntersectionExpression: TypeNode, ISymbolicTypeReference{
  14306. public TypeNodeList Types;
  14307. public TypeIntersectionExpression(TypeNodeList types)
  14308. : base(NodeType.TypeIntersectionExpression){
  14309. this.Types = types;
  14310. }
  14311. public TypeIntersectionExpression(TypeNodeList types, SourceContext sctx)
  14312. : base(NodeType.TypeIntersectionExpression){
  14313. this.Types = types;
  14314. this.SourceContext = sctx;
  14315. }
  14316. }
  14317. public class TypeUnionExpression: TypeNode, ISymbolicTypeReference{
  14318. public TypeNodeList Types;
  14319. public TypeUnionExpression(TypeNodeList types)
  14320. : base(NodeType.TypeUnionExpression){
  14321. this.Types = types;
  14322. }
  14323. public TypeUnionExpression(TypeNodeList types, SourceContext sctx)
  14324. : base(NodeType.TypeUnionExpression){
  14325. this.Types = types;
  14326. this.SourceContext = sctx;
  14327. }
  14328. }
  14329. public class TypeExpression : TypeNode, ISymbolicTypeReference{
  14330. public Expression Expression;
  14331. public int Arity;
  14332. public TypeExpression(Expression expression)
  14333. : base(NodeType.TypeExpression){
  14334. this.Expression = expression;
  14335. }
  14336. public TypeExpression(Expression expression, TypeNodeList templateArguments)
  14337. : base(NodeType.TypeExpression){
  14338. this.Expression = expression;
  14339. this.templateArguments = this.TemplateArgumentExpressions = templateArguments;
  14340. }
  14341. public TypeExpression(Expression expression, int arity)
  14342. : base(NodeType.TypeExpression) {
  14343. this.Expression = expression;
  14344. this.Arity = arity;
  14345. }
  14346. public TypeExpression(Expression expression, SourceContext sctx)
  14347. : base(NodeType.TypeExpression){
  14348. this.Expression = expression;
  14349. this.SourceContext = sctx;
  14350. }
  14351. public TypeExpression(Expression expression, TypeNodeList templateArguments, SourceContext sctx)
  14352. : base(NodeType.TypeExpression){
  14353. this.Expression = expression;
  14354. this.templateArguments = this.TemplateArgumentExpressions = templateArguments;
  14355. this.SourceContext = sctx;
  14356. }
  14357. public TypeExpression(Expression expression, int arity, SourceContext sctx)
  14358. : base(NodeType.TypeExpression) {
  14359. this.Expression = expression;
  14360. this.Arity = arity;
  14361. this.SourceContext = sctx;
  14362. }
  14363. public override bool IsUnmanaged {
  14364. get{
  14365. Literal lit = this.Expression as Literal;
  14366. if (lit != null){
  14367. TypeNode t = lit.Value as TypeNode;
  14368. if (t != null) return t.IsUnmanaged;
  14369. if (lit.Value is TypeCode) return true;
  14370. }
  14371. return true;
  14372. }
  14373. }
  14374. }
  14375. public class TypeReference : Node {
  14376. public TypeNode Type;
  14377. public TypeNode Expression;
  14378. public TypeReference(TypeNode typeExpression)
  14379. : base(NodeType.TypeReference){
  14380. this.Expression = typeExpression;
  14381. if (typeExpression != null)
  14382. this.SourceContext = typeExpression.SourceContext;
  14383. }
  14384. public TypeReference(TypeNode typeExpression, TypeNode type)
  14385. : base(NodeType.TypeReference){
  14386. this.Expression = typeExpression;
  14387. this.Type = type;
  14388. if (typeExpression != null)
  14389. this.SourceContext = typeExpression.SourceContext;
  14390. }
  14391. public static explicit operator TypeNode(TypeReference typeReference){
  14392. return null == (object)typeReference ? null : typeReference.Type;
  14393. }
  14394. public static bool operator==(TypeReference typeReference, TypeNode type){
  14395. return null == (object)typeReference ? null == (object)type : typeReference.Type == type;
  14396. }
  14397. public static bool operator==(TypeNode type, TypeReference typeReference){
  14398. return null == (object)typeReference ? null == (object)type : typeReference.Type == type;
  14399. }
  14400. public static bool operator!=(TypeReference typeReference, TypeNode type){
  14401. return null == (object)typeReference ? null != (object)type : typeReference.Type != type;
  14402. }
  14403. public static bool operator!=(TypeNode type, TypeReference typeReference){
  14404. return null == (object)typeReference ? null != (object)type : typeReference.Type != type;
  14405. }
  14406. public override bool Equals(object obj){
  14407. return obj == (object)this || obj == (object)this.Type;
  14408. }
  14409. public override int GetHashCode(){
  14410. return base.GetHashCode();
  14411. }
  14412. }
  14413. public class ArglistArgumentExpression : NaryExpression {
  14414. public ArglistArgumentExpression(ExpressionList args, SourceContext sctx) : base(args, NodeType.ArglistArgumentExpression) {
  14415. this.SourceContext = sctx;
  14416. }
  14417. }
  14418. public class ArglistExpression : Expression {
  14419. public ArglistExpression(SourceContext sctx) : base(NodeType.ArglistExpression) {
  14420. this.SourceContext = sctx;
  14421. }
  14422. }
  14423. public class RefValueExpression : BinaryExpression {
  14424. public RefValueExpression(Expression typedreference, Expression type, SourceContext sctx)
  14425. : base(typedreference, type, NodeType.RefValueExpression){
  14426. this.SourceContext = sctx;
  14427. }
  14428. }
  14429. public class RefTypeExpression : UnaryExpression {
  14430. public RefTypeExpression(Expression typedreference, SourceContext sctx)
  14431. : base(typedreference, NodeType.RefTypeExpression){
  14432. this.SourceContext = sctx;
  14433. }
  14434. }
  14435. #endif
  14436. #if ExtendedRuntime
  14437. public delegate Expression Coercer(Expression source, TypeNode targetType, TypeViewer typeViewer);
  14438. public sealed class StreamAdapter{
  14439. private StreamAdapter(){}
  14440. public static TypeNode For(Interface/*!*/ sourceStream, Interface/*!*/ targetStream, Module/*!*/ module, Coercer/*!*/ coercer, SourceContext sctx) {
  14441. return StreamAdapter.For(sourceStream, targetStream, null, module, coercer, sctx);
  14442. }
  14443. public static TypeNode For(Interface /*!*/sourceStream, Interface/*!*/ targetStream, TypeNode/*!*/ referringType, Coercer/*!*/ coercer, SourceContext sctx) {
  14444. if (referringType == null){Debug.Assert(false); return null;}
  14445. return StreamAdapter.For(sourceStream, targetStream, referringType, referringType.DeclaringModule, coercer, sctx);
  14446. }
  14447. public static TypeNode For(Interface/*!*/ sourceStream, Interface/*!*/ targetStream, TypeNode referringType, Module/*!*/ module, Coercer/*!*/ coercer, SourceContext sctx) {
  14448. Debug.Assert(sourceStream.Template == SystemTypes.GenericIEnumerable && targetStream.Template == SystemTypes.GenericIEnumerable);
  14449. Identifier id = Identifier.For("AdapterFor" + sourceStream.Name + "To" + targetStream.Name);
  14450. for (int i = 1; ;i++){
  14451. TypeNode t = module.GetStructurallyEquivalentType(targetStream.Namespace, id);
  14452. if (t == null) break;
  14453. if (t.IsAssignableTo(targetStream)){
  14454. InstanceInitializer cons = t.GetConstructor(sourceStream);
  14455. if (cons != null) return t;
  14456. }
  14457. id = Identifier.For(id.ToString()+i);
  14458. }
  14459. Method sGetEnumerator = sourceStream.GetMethod(StandardIds.GetEnumerator);
  14460. Method tGetEnumerator = targetStream.GetMethod(StandardIds.GetEnumerator);
  14461. if (sGetEnumerator == null || tGetEnumerator == null) { Debug.Fail(""); return null; }
  14462. Interface sGetEnumeratorReturnType = (Interface)TypeNode.StripModifiers(sGetEnumerator.ReturnType);
  14463. Interface tGetEnumeratorReturnType = (Interface)TypeNode.StripModifiers(tGetEnumerator.ReturnType);
  14464. //^ assert sGetEnumeratorReturnType != null && tGetEnumeratorReturnType != null;
  14465. TypeNode enumeratorAdapter = null;
  14466. if (referringType != null)
  14467. enumeratorAdapter = EnumeratorAdapter.For(id, sGetEnumeratorReturnType, tGetEnumeratorReturnType, referringType, coercer, sctx);
  14468. else
  14469. enumeratorAdapter = EnumeratorAdapter.For(id, sGetEnumeratorReturnType, tGetEnumeratorReturnType, module, coercer, sctx);
  14470. if (enumeratorAdapter == null) return null;
  14471. InterfaceList interfaces = new InterfaceList(targetStream);
  14472. MemberList members = new MemberList(3);
  14473. Class adapter = new Class(module, null, null, TypeFlags.Sealed, targetStream.Namespace, id, CoreSystemTypes.Object, interfaces, members);
  14474. adapter.IsNormalized = true;
  14475. if (referringType == null ||
  14476. (sourceStream.Flags & TypeFlags.VisibilityMask) == TypeFlags.Public && (targetStream.Flags & TypeFlags.VisibilityMask) == TypeFlags.Public){
  14477. adapter.Flags |= TypeFlags.Public;
  14478. module.Types.Add(adapter);
  14479. }else{
  14480. adapter.Flags |= TypeFlags.NestedPrivate;
  14481. referringType.Members.Add(adapter);
  14482. adapter.DeclaringType = referringType;
  14483. }
  14484. module.StructurallyEquivalentType[id.UniqueIdKey] = adapter;
  14485. //Field to hold source stream
  14486. Field ssField = new Field(adapter, null, FieldFlags.Private, StandardIds.Value, sourceStream, null);
  14487. members.Add(ssField);
  14488. //Constructor
  14489. This ThisParameter = new This(adapter);
  14490. Parameter par = new Parameter(null, ParameterFlags.None, StandardIds.Value, sourceStream, null, null);
  14491. StatementList statements = new StatementList(3);
  14492. InstanceInitializer cstr = CoreSystemTypes.Object.GetConstructor();
  14493. if (cstr == null) { Debug.Fail(""); return adapter; }
  14494. MethodCall mcall = new MethodCall(new MemberBinding(ThisParameter, cstr), new ExpressionList(0), NodeType.Call, CoreSystemTypes.Void);
  14495. statements.Add(new ExpressionStatement(mcall));
  14496. statements.Add(new AssignmentStatement(new MemberBinding(ThisParameter, ssField), par));
  14497. statements.Add(new Return());
  14498. InstanceInitializer acons = new InstanceInitializer(adapter, null, new ParameterList(par), new Block(statements));
  14499. acons.Flags |= MethodFlags.Public;
  14500. acons.ThisParameter = ThisParameter;
  14501. members.Add(acons);
  14502. //GetEnumerator
  14503. ThisParameter = new This(adapter);
  14504. statements = new StatementList(1);
  14505. mcall = new MethodCall(new MemberBinding(new MemberBinding(ThisParameter, ssField), sGetEnumerator),
  14506. new ExpressionList(0), NodeType.Callvirt, sGetEnumerator.ReturnType);
  14507. cstr = enumeratorAdapter.GetConstructor(sGetEnumerator.ReturnType);
  14508. if (cstr == null) { Debug.Fail(""); return adapter; }
  14509. Construct constr = new Construct(new MemberBinding(null, cstr), new ExpressionList(mcall));
  14510. statements.Add(new Return(constr));
  14511. Method getEnumerator = new Method(adapter, null, StandardIds.GetEnumerator, null, tGetEnumerator.ReturnType, new Block(statements));
  14512. getEnumerator.Flags = MethodFlags.Public | MethodFlags.Virtual | MethodFlags.NewSlot | MethodFlags.HideBySig;
  14513. getEnumerator.CallingConvention = CallingConventionFlags.HasThis;
  14514. getEnumerator.ThisParameter = ThisParameter;
  14515. members.Add(getEnumerator);
  14516. //IEnumerable.GetEnumerator
  14517. Method ieGetEnumerator = SystemTypes.IEnumerable.GetMethod(StandardIds.GetEnumerator);
  14518. if (ieGetEnumerator == null) { Debug.Fail(""); return adapter; }
  14519. ThisParameter = new This(adapter);
  14520. statements = new StatementList(1);
  14521. mcall = new MethodCall(new MemberBinding(new MemberBinding(ThisParameter, ssField), ieGetEnumerator),
  14522. new ExpressionList(0), NodeType.Callvirt, SystemTypes.IEnumerator);
  14523. statements.Add(new Return(mcall));
  14524. getEnumerator = new Method(adapter, null, StandardIds.IEnumerableGetEnumerator, null, SystemTypes.IEnumerator, new Block(statements));
  14525. getEnumerator.ThisParameter = ThisParameter;
  14526. getEnumerator.ImplementedInterfaceMethods = new MethodList(ieGetEnumerator);
  14527. getEnumerator.CallingConvention = CallingConventionFlags.HasThis;
  14528. getEnumerator.Flags = MethodFlags.Private | MethodFlags.Virtual | MethodFlags.SpecialName;
  14529. members.Add(getEnumerator);
  14530. return adapter;
  14531. }
  14532. }
  14533. internal sealed class EnumeratorAdapter{
  14534. private EnumeratorAdapter(){}
  14535. internal static TypeNode For(Identifier/*!*/ id, Interface/*!*/ sourceIEnumerator, Interface/*!*/ targetIEnumerator, Module/*!*/ module, Coercer/*!*/ coercer, SourceContext sctx) {
  14536. return EnumeratorAdapter.For(id, sourceIEnumerator, targetIEnumerator, null, module, coercer, sctx);
  14537. }
  14538. internal static TypeNode For(Identifier/*!*/ id, Interface/*!*/ sourceIEnumerator, Interface/*!*/ targetIEnumerator, TypeNode/*!*/ referringType, Coercer/*!*/ coercer, SourceContext sctx) {
  14539. if (referringType == null){Debug.Assert(false); return null;}
  14540. return EnumeratorAdapter.For(id, sourceIEnumerator, targetIEnumerator, referringType, referringType.DeclaringModule, coercer, sctx);
  14541. }
  14542. private static TypeNode For(Identifier/*!*/ id, Interface/*!*/ sourceIEnumerator, Interface/*!*/ targetIEnumerator, TypeNode referringType, Module/*!*/ module, Coercer/*!*/ coercer, SourceContext sctx) {
  14543. Method sGetCurrent = sourceIEnumerator.GetMethod(StandardIds.getCurrent);
  14544. if (sGetCurrent == null) { Debug.Fail(""); return null; }
  14545. Method sMoveNext = sourceIEnumerator.GetMethod(StandardIds.MoveNext);
  14546. if (sMoveNext == null) sMoveNext = SystemTypes.IEnumerator.GetMethod(StandardIds.MoveNext);
  14547. Method tGetCurrent = targetIEnumerator.GetMethod(StandardIds.getCurrent);
  14548. if (tGetCurrent == null) { Debug.Fail(""); return null; }
  14549. Method tMoveNext = targetIEnumerator.GetMethod(StandardIds.MoveNext);
  14550. if (tMoveNext == null) tMoveNext = SystemTypes.IEnumerator.GetMethod(StandardIds.MoveNext);
  14551. Local loc = new Local(sGetCurrent.ReturnType);
  14552. Expression curr = coercer(loc, tGetCurrent.ReturnType, null);
  14553. if (curr == null) return null;
  14554. id = Identifier.For("Enumerator"+id.ToString());
  14555. InterfaceList interfaces = new InterfaceList(targetIEnumerator, SystemTypes.IDisposable);
  14556. MemberList members = new MemberList(5);
  14557. Class adapter = new Class(module, null, null, TypeFlags.Public, targetIEnumerator.Namespace, id, CoreSystemTypes.Object, interfaces, members);
  14558. adapter.IsNormalized = true;
  14559. if (referringType == null ||
  14560. (sourceIEnumerator.Flags & TypeFlags.VisibilityMask) == TypeFlags.Public && (targetIEnumerator.Flags & TypeFlags.VisibilityMask) == TypeFlags.Public){
  14561. adapter.Flags |= TypeFlags.Public;
  14562. module.Types.Add(adapter);
  14563. }else{
  14564. adapter.Flags |= TypeFlags.NestedPrivate;
  14565. referringType.Members.Add(adapter);
  14566. adapter.DeclaringType = referringType;
  14567. }
  14568. //Field to hold source enumerator
  14569. Field seField = new Field(adapter, null, FieldFlags.Private, StandardIds.Value, sourceIEnumerator, null);
  14570. members.Add(seField);
  14571. //Constructor
  14572. Parameter par = new Parameter(null, ParameterFlags.None, StandardIds.Value, sourceIEnumerator, null, null);
  14573. StatementList statements = new StatementList(3);
  14574. This ThisParameter = new This(adapter);
  14575. InstanceInitializer constr = CoreSystemTypes.Object.GetConstructor();
  14576. if (constr == null) { Debug.Fail(""); return null; }
  14577. MethodCall mcall = new MethodCall(new MemberBinding(ThisParameter, constr),
  14578. new ExpressionList(0), NodeType.Call, CoreSystemTypes.Void);
  14579. statements.Add(new ExpressionStatement(mcall));
  14580. statements.Add(new AssignmentStatement(new MemberBinding(ThisParameter, seField), par));
  14581. statements.Add(new Return());
  14582. InstanceInitializer acons = new InstanceInitializer(adapter, null, new ParameterList(par), new Block(statements));
  14583. acons.Flags |= MethodFlags.Public;
  14584. acons.ThisParameter = ThisParameter;
  14585. members.Add(acons);
  14586. //get_Current
  14587. statements = new StatementList(2);
  14588. ThisParameter = new This(adapter);
  14589. mcall = new MethodCall(new MemberBinding(new MemberBinding(ThisParameter, seField), sGetCurrent),
  14590. new ExpressionList(0), NodeType.Callvirt, sGetCurrent.ReturnType);
  14591. mcall.SourceContext = sctx;
  14592. statements.Add(new AssignmentStatement(loc, mcall));
  14593. statements.Add(new Return(curr));
  14594. Method getCurrent = new Method(adapter, null, StandardIds.getCurrent, null, tGetCurrent.ReturnType, new Block(statements));
  14595. getCurrent.Flags = MethodFlags.Public | MethodFlags.Virtual | MethodFlags.NewSlot | MethodFlags.HideBySig | MethodFlags.SpecialName;
  14596. getCurrent.CallingConvention = CallingConventionFlags.HasThis;
  14597. getCurrent.ThisParameter = ThisParameter;
  14598. members.Add(getCurrent);
  14599. //IEnumerator.GetCurrent
  14600. statements = new StatementList(1);
  14601. ThisParameter = new This(adapter);
  14602. MethodCall callGetCurrent = new MethodCall(new MemberBinding(ThisParameter, getCurrent), new ExpressionList(0), NodeType.Call, getCurrent.ReturnType);
  14603. if (getCurrent.ReturnType.IsValueType) {
  14604. MemberBinding etExpr = new MemberBinding(null, getCurrent.ReturnType);
  14605. statements.Add(new Return(new BinaryExpression(callGetCurrent, etExpr, NodeType.Box, CoreSystemTypes.Object)));
  14606. }else
  14607. statements.Add(new Return(callGetCurrent));
  14608. Method ieGetCurrent = new Method(adapter, null, StandardIds.IEnumeratorGetCurrent, null, CoreSystemTypes.Object, new Block(statements));
  14609. ieGetCurrent.ThisParameter = ThisParameter;
  14610. ieGetCurrent.ImplementedInterfaceMethods = new MethodList(SystemTypes.IEnumerator.GetMethod(StandardIds.getCurrent));
  14611. ieGetCurrent.CallingConvention = CallingConventionFlags.HasThis;
  14612. ieGetCurrent.Flags = MethodFlags.Private | MethodFlags.Virtual | MethodFlags.SpecialName;
  14613. members.Add(ieGetCurrent);
  14614. //IEnumerator.Reset
  14615. Method ieReset = SystemTypes.IEnumerator.GetMethod(StandardIds.Reset);
  14616. if (ieReset == null) { Debug.Fail(""); return null; }
  14617. statements = new StatementList(2);
  14618. ThisParameter = new This(adapter);
  14619. MethodCall callSourceReset = new MethodCall(new MemberBinding(ThisParameter, ieReset), new ExpressionList(0), NodeType.Callvirt, CoreSystemTypes.Object);
  14620. statements.Add(new ExpressionStatement(callSourceReset));
  14621. statements.Add(new Return());
  14622. Method reset = new Method(adapter, null, StandardIds.IEnumeratorReset, null, CoreSystemTypes.Void, new Block(statements));
  14623. reset.ThisParameter = ThisParameter;
  14624. reset.ImplementedInterfaceMethods = new MethodList(ieReset);
  14625. reset.CallingConvention = CallingConventionFlags.HasThis;
  14626. reset.Flags = MethodFlags.Private | MethodFlags.Virtual | MethodFlags.SpecialName;
  14627. members.Add(reset);
  14628. //MoveNext
  14629. if (sMoveNext == null) { Debug.Fail(""); return null; }
  14630. statements = new StatementList(1);
  14631. ThisParameter = new This(adapter);
  14632. mcall = new MethodCall(new MemberBinding(new MemberBinding(ThisParameter, seField), sMoveNext),
  14633. new ExpressionList(0), NodeType.Callvirt, CoreSystemTypes.Boolean);
  14634. statements.Add(new Return(mcall));
  14635. Method moveNext = new Method(adapter, null, StandardIds.MoveNext, null, CoreSystemTypes.Boolean, new Block(statements));
  14636. moveNext.Flags = MethodFlags.Public | MethodFlags.Virtual | MethodFlags.NewSlot | MethodFlags.HideBySig;
  14637. moveNext.CallingConvention = CallingConventionFlags.HasThis;
  14638. moveNext.ThisParameter = ThisParameter;
  14639. members.Add(moveNext);
  14640. //IDispose.Dispose
  14641. statements = new StatementList(1);
  14642. //TODO: call Dispose on source enumerator
  14643. statements.Add(new Return());
  14644. Method dispose = new Method(adapter, null, StandardIds.Dispose, null, CoreSystemTypes.Void, new Block(statements));
  14645. dispose.CallingConvention = CallingConventionFlags.HasThis;
  14646. dispose.Flags = MethodFlags.Public | MethodFlags.Virtual;
  14647. adapter.Members.Add(dispose);
  14648. return adapter;
  14649. }
  14650. }
  14651. #endif
  14652. #if FxCop
  14653. public class EventNode : Member{
  14654. #else
  14655. public class Event : Member{
  14656. #endif
  14657. private EventFlags flags;
  14658. private Method handlerAdder;
  14659. private Method handlerCaller;
  14660. private MethodFlags handlerFlags;
  14661. private Method handlerRemover;
  14662. private TypeNode handlerType;
  14663. private MethodList otherMethods;
  14664. #if !MinimalReader
  14665. public TypeNode HandlerTypeExpression;
  14666. /// <summary>The list of types (just one in C#) that contain abstract or virtual events that are explicity implemented or overridden by this event.</summary>
  14667. public TypeNodeList ImplementedTypes;
  14668. public TypeNodeList ImplementedTypeExpressions;
  14669. /// <summary>Provides a delegate instance that is added to the event upon initialization.</summary>
  14670. public Expression InitialHandler;
  14671. public Field BackingField;
  14672. #endif
  14673. #if FxCop
  14674. public EventNode()
  14675. #else
  14676. public Event()
  14677. #endif
  14678. : base(NodeType.Event){
  14679. }
  14680. #if !MinimalReader
  14681. public Event(TypeNode declaringType, AttributeList attributes, EventFlags flags, Identifier name,
  14682. Method handlerAdder, Method handlerCaller, Method handlerRemover, TypeNode handlerType)
  14683. : base(declaringType, attributes, name, NodeType.Event){
  14684. this.Flags = flags;
  14685. this.HandlerAdder = handlerAdder;
  14686. this.HandlerCaller = handlerCaller;
  14687. this.HandlerRemover = handlerRemover;
  14688. this.HandlerType = handlerType;
  14689. }
  14690. #endif
  14691. /// <summary>Bits characterizing this event.</summary>
  14692. public EventFlags Flags{
  14693. get{return this.flags;}
  14694. set{this.flags = value;}
  14695. }
  14696. /// <summary>The method to be called in order to add a handler to an event. Corresponds to the add clause of a C# event declaration.</summary>
  14697. public Method HandlerAdder{
  14698. get{return this.handlerAdder;}
  14699. set{this.handlerAdder = value;}
  14700. }
  14701. /// <summary>The method that gets called to fire an event. There is no corresponding C# syntax.</summary>
  14702. public Method HandlerCaller{
  14703. get{return this.handlerCaller;}
  14704. set{this.handlerCaller = value;}
  14705. }
  14706. public MethodFlags HandlerFlags{
  14707. get{return this.handlerFlags;}
  14708. set{this.handlerFlags = value;}
  14709. }
  14710. /// <summary>The method to be called in order to remove a handler from an event. Corresponds to the remove clause of a C# event declaration.</summary>
  14711. public Method HandlerRemover{
  14712. get{return this.handlerRemover;}
  14713. set{this.handlerRemover = value;}
  14714. }
  14715. /// <summary>The delegate type that a handler for this event must have. Corresponds to the type clause of C# event declaration.</summary>
  14716. public TypeNode HandlerType{
  14717. get{return this.handlerType;}
  14718. set{this.handlerType = value;}
  14719. }
  14720. public MethodList OtherMethods{
  14721. get{return this.otherMethods;}
  14722. set{this.otherMethods = value;}
  14723. }
  14724. protected string fullName;
  14725. public override string/*!*/ FullName {
  14726. get{
  14727. string result = this.fullName;
  14728. if (result == null)
  14729. this.fullName = result = this.DeclaringType.FullName+"."+(this.Name == null ? "" : this.Name.ToString());
  14730. return result;
  14731. }
  14732. }
  14733. #if !NoXml
  14734. protected override Identifier GetDocumentationId(){
  14735. StringBuilder sb = new StringBuilder();
  14736. sb.Append("E:");
  14737. if (this.DeclaringType == null) return Identifier.Empty;
  14738. this.DeclaringType.AppendDocumentIdMangledName(sb, null, null);
  14739. sb.Append(".");
  14740. if (this.Name == null) return Identifier.Empty;
  14741. sb.Append(this.Name.Name);
  14742. return Identifier.For(sb.ToString());
  14743. }
  14744. #endif
  14745. #if !NoReflection
  14746. public static Event GetEvent(System.Reflection.EventInfo eventInfo){
  14747. if (eventInfo == null) return null;
  14748. TypeNode tn = TypeNode.GetTypeNode(eventInfo.DeclaringType);
  14749. if (tn == null) return null;
  14750. return tn.GetEvent(Identifier.For(eventInfo.Name));
  14751. }
  14752. protected System.Reflection.EventInfo eventInfo;
  14753. public virtual System.Reflection.EventInfo GetEventInfo(){
  14754. if (this.eventInfo == null){
  14755. TypeNode tn = this.DeclaringType;
  14756. if (tn == null) return null;
  14757. Type t = tn.GetRuntimeType();
  14758. if (t == null) return null;
  14759. System.Reflection.BindingFlags flags = System.Reflection.BindingFlags.DeclaredOnly;
  14760. if (this.IsPublic) flags |= System.Reflection.BindingFlags.Public; else flags |= System.Reflection.BindingFlags.NonPublic;
  14761. if (this.IsStatic) flags |= System.Reflection.BindingFlags.Static; else flags |= System.Reflection.BindingFlags.Instance;
  14762. this.eventInfo = t.GetEvent(this.Name.ToString(), flags);
  14763. }
  14764. return this.eventInfo;
  14765. }
  14766. #endif
  14767. /// <summary>
  14768. /// True if the methods constituting this event are abstract.
  14769. /// </summary>
  14770. public bool IsAbstract{
  14771. get{return (this.HandlerFlags & MethodFlags.Abstract) != 0;}
  14772. }
  14773. public override bool IsAssembly{
  14774. get{return (this.HandlerFlags & MethodFlags.MethodAccessMask) == MethodFlags.Assembly;}
  14775. }
  14776. public override bool IsCompilerControlled{
  14777. get{return (this.HandlerFlags & MethodFlags.MethodAccessMask) == MethodFlags.CompilerControlled;}
  14778. }
  14779. public override bool IsFamily{
  14780. get{return (this.HandlerFlags & MethodFlags.MethodAccessMask) == MethodFlags.Family;}
  14781. }
  14782. public override bool IsFamilyAndAssembly{
  14783. get{return (this.HandlerFlags & MethodFlags.MethodAccessMask) == MethodFlags.FamANDAssem;}
  14784. }
  14785. public override bool IsFamilyOrAssembly{
  14786. get{return (this.HandlerFlags & MethodFlags.MethodAccessMask) == MethodFlags.FamORAssem;}
  14787. }
  14788. public bool IsFinal {
  14789. get { return (this.HandlerFlags & MethodFlags.Final) != 0; }
  14790. }
  14791. public override bool IsPrivate {
  14792. get{return (this.HandlerFlags & MethodFlags.MethodAccessMask) == MethodFlags.Private;}
  14793. }
  14794. public override bool IsPublic{
  14795. get{return (this.HandlerFlags & MethodFlags.MethodAccessMask) == MethodFlags.Public;}
  14796. }
  14797. public override bool IsSpecialName{
  14798. get{return (this.Flags & EventFlags.SpecialName) != 0;}
  14799. }
  14800. public override bool IsStatic{
  14801. get{return (this.HandlerFlags & MethodFlags.Static) != 0;}
  14802. }
  14803. /// <summary>
  14804. /// True if that the methods constituting this event are virtual.
  14805. /// </summary>
  14806. public bool IsVirtual{
  14807. get{return (this.HandlerFlags & MethodFlags.Virtual) != 0;}
  14808. }
  14809. public override bool IsVisibleOutsideAssembly{
  14810. get{
  14811. return (this.HandlerAdder != null && this.HandlerAdder.IsVisibleOutsideAssembly) ||
  14812. (this.HandlerCaller != null && this.HandlerCaller.IsVisibleOutsideAssembly) ||
  14813. (this.HandlerRemover != null && this.HandlerRemover.IsVisibleOutsideAssembly);
  14814. }
  14815. }
  14816. public static readonly Event NotSpecified = new Event();
  14817. public override Member HiddenMember{
  14818. get{
  14819. return this.HiddenEvent;
  14820. }
  14821. set{
  14822. this.HiddenEvent = (Event)value;
  14823. }
  14824. }
  14825. protected Property hiddenEvent;
  14826. public virtual Event HiddenEvent{
  14827. get{
  14828. if (this.hiddenMember == Event.NotSpecified) return null;
  14829. Event hiddenEvent = this.hiddenMember as Event;
  14830. if (hiddenEvent != null) return hiddenEvent;
  14831. Method hiddenAdder = this.HandlerAdder == null ? null : this.HandlerAdder.HiddenMethod;
  14832. Method hiddenCaller = this.HandlerCaller == null ? null : this.HandlerCaller.HiddenMethod;
  14833. Method hiddenRemover = this.HandlerRemover == null ? null : this.HandlerRemover.HiddenMethod;
  14834. Event hiddenAdderEvent = hiddenAdder == null ? null : hiddenAdder.DeclaringMember as Event;
  14835. Event hiddenCallerEvent = hiddenCaller == null ? null : hiddenCaller.DeclaringMember as Event;
  14836. Event hiddenRemoverEvent = hiddenRemover == null ? null : hiddenRemover.DeclaringMember as Event;
  14837. hiddenEvent = hiddenAdderEvent;
  14838. if (hiddenCallerEvent != null){
  14839. if (hiddenEvent == null ||
  14840. (hiddenCallerEvent.DeclaringType != null && hiddenCallerEvent.DeclaringType.IsDerivedFrom(hiddenEvent.DeclaringType)))
  14841. hiddenEvent = hiddenCallerEvent;
  14842. }
  14843. if (hiddenRemoverEvent != null){
  14844. if (hiddenEvent == null ||
  14845. (hiddenRemoverEvent.DeclaringType != null && hiddenRemoverEvent.DeclaringType.IsDerivedFrom(hiddenEvent.DeclaringType)))
  14846. hiddenEvent = hiddenRemoverEvent;
  14847. }
  14848. if (hiddenEvent == null){
  14849. this.hiddenMember = Event.NotSpecified;
  14850. return null;
  14851. }
  14852. this.hiddenMember = hiddenEvent;
  14853. return hiddenEvent;
  14854. }
  14855. set{
  14856. this.hiddenMember = value;
  14857. }
  14858. }
  14859. public override Member OverriddenMember{
  14860. get{
  14861. return this.OverriddenEvent;
  14862. }
  14863. set{
  14864. this.OverriddenEvent = (Event)value;
  14865. }
  14866. }
  14867. protected Property overriddenEvent;
  14868. public virtual Event OverriddenEvent{
  14869. get{
  14870. if (this.overriddenMember == Event.NotSpecified) return null;
  14871. Event overriddenEvent = this.overriddenMember as Event;
  14872. if (overriddenEvent != null) return overriddenEvent;
  14873. Method overriddenAdder = this.HandlerAdder == null ? null : this.HandlerAdder.OverriddenMethod;
  14874. Method overriddenCaller = this.HandlerCaller == null ? null : this.HandlerCaller.OverriddenMethod;
  14875. Method overriddenRemover = this.HandlerRemover == null ? null : this.HandlerRemover.OverriddenMethod;
  14876. Event overriddenAdderEvent = overriddenAdder == null ? null : overriddenAdder.DeclaringMember as Event;
  14877. Event overriddenCallerEvent = overriddenCaller == null ? null : overriddenCaller.DeclaringMember as Event;
  14878. Event overriddenRemoverEvent = overriddenRemover == null ? null : overriddenRemover.DeclaringMember as Event;
  14879. overriddenEvent = overriddenAdderEvent;
  14880. if (overriddenCallerEvent != null){
  14881. if (overriddenEvent == null ||
  14882. (overriddenCallerEvent.DeclaringType != null && overriddenCallerEvent.DeclaringType.IsDerivedFrom(overriddenEvent.DeclaringType)))
  14883. overriddenEvent = overriddenCallerEvent;
  14884. }
  14885. if (overriddenRemoverEvent != null){
  14886. if (overriddenEvent == null ||
  14887. (overriddenRemoverEvent.DeclaringType != null && overriddenRemoverEvent.DeclaringType.IsDerivedFrom(overriddenEvent.DeclaringType)))
  14888. overriddenEvent = overriddenRemoverEvent;
  14889. }
  14890. if (overriddenEvent == null){
  14891. this.overriddenMember = Event.NotSpecified;
  14892. return null;
  14893. }
  14894. this.overriddenMember = overriddenEvent;
  14895. return overriddenEvent;
  14896. }
  14897. set{
  14898. this.overriddenMember = value;
  14899. }
  14900. }
  14901. #if FxCop
  14902. internal override void GetName(MemberFormat options, StringBuilder name)
  14903. {
  14904. base.GetName(options, name);
  14905. Method.AppendReturnType(options.ReturnType, this.HandlerType, name);
  14906. }
  14907. #endif
  14908. }
  14909. #if ExtendedRuntime
  14910. public abstract class MethodContractElement : Node{
  14911. protected MethodContractElement(NodeType nodeType)
  14912. : base(nodeType){
  14913. }
  14914. public bool Inherited;
  14915. #if !FxCop && ILOFFSETS
  14916. public int ILOffset;
  14917. // a string that a user wants associated with a particular element
  14918. public Expression UserMessage;
  14919. public Literal SourceConditionText;
  14920. #endif
  14921. }
  14922. public abstract class Requires : MethodContractElement {
  14923. public Expression Condition;
  14924. public virtual bool IsWithException { get { return false; } }
  14925. protected Requires()
  14926. : base(NodeType.Requires) {}
  14927. protected Requires(NodeType nodeType)
  14928. : base(nodeType){
  14929. }
  14930. protected Requires(NodeType nodeType, Expression expression)
  14931. : base(nodeType){
  14932. Condition = expression;
  14933. }
  14934. }
  14935. public class RequiresPlain : Requires {
  14936. /// <summary>
  14937. /// If non-null, indicates that this is a Requires&lt;TException&gt; form throwing TException
  14938. /// </summary>
  14939. public TypeNode ExceptionType;
  14940. public override bool IsWithException
  14941. {
  14942. get { return this.ExceptionType != null; }
  14943. }
  14944. public RequiresPlain()
  14945. : base(NodeType.RequiresPlain) {}
  14946. public RequiresPlain(Expression expression)
  14947. : base(NodeType.RequiresPlain, expression) {}
  14948. public RequiresPlain(Expression expression, TypeNode texception)
  14949. : base(NodeType.RequiresPlain, expression) {
  14950. this.ExceptionType = texception;
  14951. }
  14952. }
  14953. public class OldExpression : Expression {
  14954. public Expression expression;
  14955. public OldExpression()
  14956. : base(NodeType.OldExpression) {}
  14957. public OldExpression(Expression expression)
  14958. : base(NodeType.OldExpression) {this.expression = expression;}
  14959. public int ShallowCopyUptoDimension {
  14960. get {
  14961. return copyLevel;
  14962. }
  14963. set {
  14964. copyLevel = value;
  14965. }
  14966. }
  14967. private int copyLevel = 0;
  14968. }
  14969. public class RequiresOtherwise : Requires {
  14970. /// <summary>
  14971. /// The ThrowException can be a type reference (like "NullReferenceException")
  14972. /// or a value that would evaluate to something of an exception type.
  14973. /// (like new NullReferenceException("...") or C.f where the f is a static field
  14974. /// of class C whose type is an exception.
  14975. /// </summary>
  14976. public Expression ThrowException;
  14977. public RequiresOtherwise()
  14978. : base(NodeType.RequiresOtherwise) {}
  14979. public RequiresOtherwise(Expression cond, Expression exc)
  14980. : base(NodeType.RequiresOtherwise, cond){ ThrowException = exc; }
  14981. }
  14982. abstract public class Ensures : MethodContractElement {
  14983. public Expression PostCondition;
  14984. protected Ensures()
  14985. : base(NodeType.Ensures) {}
  14986. protected Ensures(NodeType nodeType)
  14987. : base(nodeType){
  14988. }
  14989. protected Ensures(NodeType nodeType, Expression expression)
  14990. : base(nodeType){
  14991. this.PostCondition = expression;
  14992. }
  14993. }
  14994. public class EnsuresNormal : Ensures{
  14995. public EnsuresNormal()
  14996. : base(NodeType.EnsuresNormal){
  14997. }
  14998. public EnsuresNormal(Expression expression)
  14999. : base(NodeType.EnsuresNormal, expression){
  15000. }
  15001. }
  15002. public class EnsuresExceptional : Ensures{
  15003. public TypeNode Type;
  15004. public TypeNode TypeExpression;
  15005. public Expression Variable;
  15006. public EnsuresExceptional()
  15007. : base(NodeType.EnsuresExceptional){
  15008. }
  15009. public EnsuresExceptional(Expression expression)
  15010. : base(NodeType.EnsuresExceptional, expression){
  15011. }
  15012. }
  15013. public class ContractDeserializerContainer{
  15014. public static IContractDeserializer ContractDeserializer;
  15015. }
  15016. public class MethodContract : Node{
  15017. public Method/*!*/ DeclaringMethod;
  15018. public Method/*!*/ OriginalDeclaringMethod;
  15019. /// <summary>
  15020. /// Used when contract are extracted from code and the contract use delegates with closure objects
  15021. /// </summary>
  15022. protected internal Block contractInitializer;
  15023. protected internal RequiresList requires;
  15024. protected internal EnsuresList ensures;
  15025. protected internal ExpressionList modifies;
  15026. protected internal bool? isPure;
  15027. private static SourceContext SetContext(string/*!*/ filename, int startLine, int startCol, int endLine, int endCol, string/*!*/ sourceText) {
  15028. SourceContext context;
  15029. context.Document = new DocumentWithPrecomputedLineNumbers(filename, startLine, startCol, endLine, endCol);
  15030. context.StartPos = 0;
  15031. context.EndPos = sourceText.Length;
  15032. context.Document.Text = new DocumentText(sourceText);
  15033. context.Document.Text.Length = sourceText.Length;
  15034. return context;
  15035. }
  15036. public static SourceContext GetSourceContext(AttributeNode/*!*/ attr) {
  15037. string filename = "";
  15038. int startLine = 0;
  15039. int startCol = 0;
  15040. int endLine = 0;
  15041. int endCol = 0;
  15042. string sourceText = "";
  15043. if (attr.Expressions != null) {
  15044. for (int expIndex = 1, expLen = attr.Expressions.Count; expIndex < expLen; expIndex++) {
  15045. NamedArgument na = attr.Expressions[expIndex] as NamedArgument;
  15046. if (na == null || na.Name == null) continue;
  15047. Literal lit = na.Value as Literal;
  15048. if (lit == null) continue;
  15049. switch (na.Name.Name) {
  15050. case "Filename":
  15051. case "FileName":
  15052. filename = (string)lit.Value; break;
  15053. case "StartColumn": startCol = (int)lit.Value; break;
  15054. case "StartLine": startLine = (int)lit.Value; break;
  15055. case "EndColumn": endCol = (int)lit.Value; break;
  15056. case "EndLine": endLine = (int)lit.Value; break;
  15057. case "SourceText": sourceText = (string)lit.Value; break;
  15058. default: break;
  15059. }
  15060. }
  15061. }
  15062. SourceContext ctx = SetContext(filename, startLine, startCol, endLine, endCol,sourceText);
  15063. return ctx;
  15064. }
  15065. public Block ContractInitializer
  15066. {
  15067. get
  15068. {
  15069. // materialize contract if this is an instance
  15070. if (contractInitializer == null) SpecializeContract();
  15071. return contractInitializer;
  15072. }
  15073. set
  15074. {
  15075. this.contractInitializer = value;
  15076. }
  15077. }
  15078. #if false
  15079. public Block ContractLocalsInitializer
  15080. {
  15081. get
  15082. {
  15083. // materialize contract if this is an instance
  15084. if (contractLocalsInitializer == null) SpecializeContract();
  15085. return contractLocalsInitializer;
  15086. }
  15087. set
  15088. {
  15089. this.contractLocalsInitializer = value;
  15090. }
  15091. }
  15092. #endif
  15093. private void SpecializeContract()
  15094. {
  15095. if (this.Specializer == null) return;
  15096. if (this.DeclaringMethod == null) return;
  15097. Method template = this.DeclaringMethod.Template;
  15098. if (template == null) return;
  15099. this.CopyFrom(template.Contract);
  15100. this.contractInitializer = (Block)this.Specializer(this.DeclaringMethod, this.contractInitializer);
  15101. this.ensures = (EnsuresList)this.Specializer(this.DeclaringMethod, this.ensures);
  15102. this.requires = (RequiresList)this.Specializer(this.DeclaringMethod, this.requires);
  15103. this.Specializer = null;
  15104. }
  15105. public RequiresList Requires{
  15106. get{
  15107. if (this.requires != null) return this.requires;
  15108. RequiresList rs = this.requires = new RequiresList();
  15109. if (this.DeclaringMethod != null){
  15110. if (this.Specializer != null && this.DeclaringMethod.Template != null) {
  15111. SpecializeContract();
  15112. return this.requires;
  15113. }
  15114. AttributeList attributes = this.DeclaringMethod.Attributes;
  15115. if (attributes == null || attributes.Count == 0) return rs;
  15116. IContractDeserializer ds = Cci.ContractDeserializerContainer.ContractDeserializer;
  15117. if (ds != null){
  15118. TypeNode t = this.DeclaringMethod.DeclaringType;
  15119. Module savedCurrentAssembly = ds.CurrentAssembly;
  15120. ds.CurrentAssembly = t == null ? null : t.DeclaringModule;
  15121. for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++){
  15122. AttributeNode attr = attributes[i];
  15123. if (attr == null) continue;
  15124. MemberBinding mb = attr.Constructor as MemberBinding;
  15125. if (mb != null){
  15126. if (mb.BoundMember == null) continue;
  15127. if (mb.BoundMember.DeclaringType != SystemTypes.RequiresAttribute) continue;
  15128. if (attr.Expressions == null || !(attr.Expressions.Count > 0)) continue;
  15129. Literal l = attr.Expressions[0] as Literal;
  15130. if (l == null) continue;
  15131. string s = (string) l.Value;
  15132. Expression e = null;
  15133. try {
  15134. e = ds.ParseContract(this,s,null);
  15135. } catch {
  15136. continue; //return this.requires = new RequiresList();
  15137. }
  15138. if (e != null){
  15139. RequiresPlain rp = new RequiresPlain(e);
  15140. SourceContext ctx = MethodContract.GetSourceContext(attr);
  15141. e.SourceContext = ctx;
  15142. rs.Add(rp);
  15143. }
  15144. }
  15145. }
  15146. ds.CurrentAssembly = savedCurrentAssembly;
  15147. }
  15148. }
  15149. return this.requires;
  15150. }
  15151. set{
  15152. this.requires = value;
  15153. }
  15154. }
  15155. public EnsuresList Ensures{
  15156. get{
  15157. if (this.ensures != null) return this.ensures;
  15158. EnsuresList es = this.ensures = new EnsuresList();
  15159. if (this.DeclaringMethod != null){
  15160. if (this.Specializer != null && this.DeclaringMethod.Template != null) {
  15161. SpecializeContract();
  15162. return this.ensures;
  15163. }
  15164. AttributeList attributes = this.DeclaringMethod.Attributes;
  15165. if (attributes == null || attributes.Count == 0) return es;
  15166. IContractDeserializer ds = Cci.ContractDeserializerContainer.ContractDeserializer;
  15167. if (ds != null){
  15168. TypeNode t = this.DeclaringMethod.DeclaringType;
  15169. Module savedCurrentAssembly = ds.CurrentAssembly;
  15170. ds.CurrentAssembly = t == null ? null : t.DeclaringModule;
  15171. for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++){
  15172. AttributeNode attr = attributes[i];
  15173. if (attr == null) continue;
  15174. MemberBinding mb = attr.Constructor as MemberBinding;
  15175. if (mb != null){
  15176. if (mb.BoundMember == null) continue;
  15177. if (mb.BoundMember.DeclaringType == SystemTypes.ThrowsAttribute) {
  15178. EnsuresExceptional ee = null;
  15179. Literal eeType = attr.Expressions[0] as Literal;
  15180. if (eeType == null) continue;
  15181. if (eeType.Type == SystemTypes.Type) {
  15182. TypeNode tn = (TypeNode)eeType.Value;
  15183. ee = new EnsuresExceptional();
  15184. ee.Type = tn;
  15185. es.Add(ee);
  15186. }
  15187. if (ee != null && attr.Expressions.Count > 1) {
  15188. Literal eeCondition = attr.Expressions[1] as Literal;
  15189. if (eeCondition != null) {
  15190. string eeString = (string)eeCondition.Value;
  15191. Expression deserializedEECondition = null;
  15192. try {
  15193. deserializedEECondition = ds.ParseContract(this, eeString, null);
  15194. Comprehension cmp = deserializedEECondition as Comprehension;
  15195. if (cmp != null) {
  15196. // See notes in Serializer for how this is represented
  15197. ComprehensionBinding cmpB = (ComprehensionBinding)cmp.BindingsAndFilters[0];
  15198. ee.Variable = cmpB.TargetVariable;
  15199. ee.PostCondition = cmp.Elements[0];
  15200. } else {
  15201. ee.PostCondition = deserializedEECondition;
  15202. }
  15203. SourceContext eeSourceContext = MethodContract.GetSourceContext(attr);
  15204. ee.PostCondition.SourceContext = eeSourceContext;
  15205. }
  15206. catch {
  15207. continue; //return this.ensures = new EnsuresList();
  15208. }
  15209. }
  15210. }
  15211. }
  15212. if (mb.BoundMember.DeclaringType != SystemTypes.EnsuresAttribute) continue;
  15213. if (attr.Expressions == null || !(attr.Expressions.Count > 0)) continue;
  15214. Literal l = attr.Expressions[0] as Literal;
  15215. if (l == null) continue;
  15216. string s = (string) l.Value;
  15217. Expression e = null;
  15218. try {
  15219. e = ds.ParseContract(this,s,null);
  15220. } catch {
  15221. continue; //return this.ensures = new EnsuresList();
  15222. }
  15223. EnsuresNormal ens = new EnsuresNormal(e);
  15224. SourceContext ctx = MethodContract.GetSourceContext(attr);
  15225. e.SourceContext = ctx;
  15226. es.Add(ens);
  15227. }
  15228. }
  15229. ds.CurrentAssembly = savedCurrentAssembly;
  15230. }
  15231. }
  15232. return this.ensures;
  15233. }
  15234. set{
  15235. this.ensures = value;
  15236. }
  15237. }
  15238. public bool IsPure
  15239. {
  15240. get
  15241. {
  15242. if (this.isPure.HasValue) return this.isPure.Value;
  15243. if (this.DeclaringMethod != null)
  15244. {
  15245. AttributeList attributes = this.DeclaringMethod.Attributes;
  15246. for (int i = 0; attributes != null && i < attributes.Count; i++)
  15247. {
  15248. AttributeNode attr = attributes[i];
  15249. if (attr == null) continue;
  15250. if (attr.Type == null) continue;
  15251. if (attr.Type.Name == null) continue;
  15252. if (attr.Type.Name.Name == "PureAttribute")
  15253. {
  15254. this.isPure = true;
  15255. return true;
  15256. }
  15257. }
  15258. }
  15259. this.isPure = false;
  15260. return false;
  15261. }
  15262. }
  15263. public ExpressionList Modifies{
  15264. get{
  15265. if (this.modifies != null) return this.modifies;
  15266. ExpressionList ms = this.modifies = new ExpressionList();
  15267. if (this.DeclaringMethod != null){
  15268. AttributeList attributes = this.DeclaringMethod.Attributes;
  15269. if (attributes == null || attributes.Count == 0) return ms;
  15270. IContractDeserializer ds = Cci.ContractDeserializerContainer.ContractDeserializer;
  15271. if (ds != null){
  15272. TypeNode t = this.DeclaringMethod.DeclaringType;
  15273. Module savedCurrentAssembly = ds.CurrentAssembly;
  15274. ds.CurrentAssembly = t == null ? null : t.DeclaringModule;
  15275. for (int i = 0, n = attributes == null || attributes.Count == 0 ? 0 : attributes.Count; i < n; i++) {
  15276. AttributeNode attr = attributes[i];
  15277. if (attr == null) continue;
  15278. MemberBinding mb = attr.Constructor as MemberBinding;
  15279. if (mb != null){
  15280. if (mb.BoundMember == null) continue;
  15281. if (mb.BoundMember.DeclaringType != SystemTypes.ModifiesAttribute) continue;
  15282. if (attr.Expressions == null || !(attr.Expressions.Count > 0)) continue;
  15283. Literal l = attr.Expressions[0] as Literal;
  15284. if (l == null) continue;
  15285. string s = (string) l.Value;
  15286. Expression e = ds.ParseContract(this,s,null);
  15287. if (e == null) continue;
  15288. SourceContext ctx = MethodContract.GetSourceContext(attr);
  15289. e.SourceContext = ctx;
  15290. ms.Add(e);
  15291. }
  15292. }
  15293. ds.CurrentAssembly = savedCurrentAssembly;
  15294. }
  15295. }
  15296. return this.modifies;
  15297. }
  15298. set{
  15299. this.modifies = value;
  15300. }
  15301. }
  15302. public delegate object ContractSpecializerDelegate(Method method, object part);
  15303. public ContractSpecializerDelegate Specializer;
  15304. public MethodContract(Method/*!*/ declaringMethod)
  15305. : base(NodeType.MethodContract) {
  15306. this.DeclaringMethod = this.OriginalDeclaringMethod = declaringMethod;
  15307. }
  15308. public void CopyFrom(MethodContract sourceContract) {
  15309. if ( sourceContract == null ) return;
  15310. this.OriginalDeclaringMethod = sourceContract.OriginalDeclaringMethod;
  15311. // Force deserialization (if necessary) to make sure sourceContract is fully populated
  15312. // This is needed for LocalForResult: it is populated in the sourceContract only if the
  15313. // postconditions have been deserialized.
  15314. int dummy = sourceContract.Requires.Count;
  15315. dummy = sourceContract.Ensures.Count + dummy;
  15316. TypeNode t = this.DeclaringMethod.DeclaringType;
  15317. Module m = t.DeclaringModule;
  15318. Duplicator dup = new Duplicator(m,t);
  15319. // Set up DuplicateFor table: all references to parameters from the source contract should be replaced
  15320. // with references to the equivalent parameter from the target contract.
  15321. // These references can be of type "Parameter" or "ParameterField".
  15322. // Also, the local that holds the "result" of the method should be likewise mapped.
  15323. // Also, the "this" parameter should be mapped.
  15324. Method sourceMethod = sourceContract.DeclaringMethod;
  15325. if (sourceMethod != null){
  15326. MethodScope sourceScope = sourceMethod.Scope;
  15327. Method targetMethod = this.DeclaringMethod;
  15328. if (targetMethod != null){
  15329. #region Map the self parameter
  15330. if (sourceMethod.ThisParameter != null && targetMethod.ThisParameter != null){
  15331. dup.DuplicateFor[sourceMethod.ThisParameter.UniqueKey] = targetMethod.ThisParameter;
  15332. }
  15333. #endregion
  15334. #region Map the method parameters
  15335. if (sourceMethod.Parameters != null && targetMethod.Parameters != null
  15336. && sourceMethod.Parameters.Count == targetMethod.Parameters.Count){
  15337. for (int i = 0, n = sourceMethod.Parameters.Count; i < n; i++){
  15338. dup.DuplicateFor[sourceMethod.Parameters[i].UniqueKey] = targetMethod.Parameters[i];
  15339. }
  15340. }
  15341. #endregion
  15342. #region Map the ParameterFields
  15343. MethodScope targetScope = targetMethod.Scope;
  15344. if (sourceScope != null && targetScope != null){
  15345. MemberList sourceScopeMembers = sourceScope.Members;
  15346. for (int i = 0, n = sourceScopeMembers != null ? sourceScopeMembers.Count : 0; i < n; i++){
  15347. ParameterField sourcePF = sourceScopeMembers[i] as ParameterField;
  15348. if (sourcePF == null) continue;
  15349. Parameter sourceP = sourcePF.Parameter;
  15350. if (sourceP == null){ Debug.Assert(false); continue; }
  15351. int index = sourceP.ParameterListIndex;
  15352. if (targetMethod.Parameters == null || targetMethod.Parameters.Count <= index || index < 0){
  15353. Debug.Assert(false); continue;
  15354. }
  15355. Parameter targetParameter = targetMethod.Parameters[index];
  15356. Field f = targetScope.GetField(targetParameter.Name);
  15357. if (f == null){ Debug.Assert(false); continue; }
  15358. ParameterField targetPF = f as ParameterField;
  15359. if (targetPF == null){ Debug.Assert(false); continue; }
  15360. dup.DuplicateFor[sourcePF.UniqueKey] = targetPF;
  15361. }
  15362. }
  15363. #endregion
  15364. }
  15365. }
  15366. MethodContract duplicatedMC = dup.VisitMethodContract(sourceContract);
  15367. duplicatedMC.isPure = sourceContract.IsPure; // force looking at attributes
  15368. if (duplicatedMC != null && duplicatedMC.Requires != null && duplicatedMC.Requires.Count > 0) {
  15369. RequiresList reqList = new RequiresList();
  15370. for (int i = 0, n = duplicatedMC.Requires.Count; i< n; i++){
  15371. Requires r = duplicatedMC.Requires[i];
  15372. if (r != null) r.Inherited = true;
  15373. reqList.Add(r);
  15374. }
  15375. if (this.requires != null)
  15376. {
  15377. foreach (Requires r in this.requires)
  15378. {
  15379. reqList.Add(r);
  15380. }
  15381. }
  15382. this.Requires = reqList;
  15383. }
  15384. if (duplicatedMC != null && duplicatedMC.Ensures != null && duplicatedMC.Ensures.Count > 0 ) {
  15385. EnsuresList enList = new EnsuresList();
  15386. for(int i = 0, n = duplicatedMC.Ensures.Count; i < n; i++) {
  15387. Ensures e = duplicatedMC.Ensures[i];
  15388. if (e == null) continue;
  15389. e.Inherited = true;
  15390. enList.Add(e);
  15391. }
  15392. if (this.ensures != null)
  15393. {
  15394. foreach (Ensures e in this.ensures)
  15395. {
  15396. enList.Add(e);
  15397. }
  15398. }
  15399. this.Ensures = enList;
  15400. }
  15401. if (duplicatedMC != null && duplicatedMC.Modifies != null && duplicatedMC.Modifies.Count > 0) {
  15402. ExpressionList modlist = this.Modifies = (this.Modifies == null ? new ExpressionList() : this.Modifies);
  15403. for (int i = 0, n = duplicatedMC.Modifies.Count; i < n; i++)
  15404. modlist.Add(duplicatedMC.Modifies[i]);
  15405. }
  15406. this.ContractInitializer = duplicatedMC.ContractInitializer;
  15407. return;
  15408. }
  15409. }
  15410. /// <summary>
  15411. /// This is a method, as we need a binding for "this".
  15412. /// </summary>
  15413. public class Invariant : Method{
  15414. public Expression Condition;
  15415. #if !FxCop && ILOFFSETS
  15416. public int ILOffset;
  15417. // a string that a user wants associated with a particular element
  15418. public Literal UserMessage;
  15419. public Literal SourceConditionText;
  15420. #endif
  15421. public Invariant(TypeNode declaringType, AttributeList attributes, Identifier name)
  15422. {
  15423. this.NodeType = NodeType.Invariant;
  15424. this.attributes = attributes;
  15425. this.DeclaringType = declaringType;
  15426. this.Name = name;
  15427. // this is called from the parser, so we have to avoid triggering CoreSystemType initialization.
  15428. this.ReturnType = new TypeExpression(new Literal(TypeCode.Boolean), 0);
  15429. this.ReturnTypeExpression = new TypeExpression(new Literal(TypeCode.Boolean), 0);
  15430. }
  15431. // called from Foxtrot
  15432. public Invariant(TypeNode declaringType, Expression invariant, string name)
  15433. {
  15434. this.NodeType = NodeType.Invariant;
  15435. this.DeclaringType = declaringType;
  15436. this.Condition = invariant;
  15437. if (name == null)
  15438. {
  15439. name = "ObjectInvariant";
  15440. }
  15441. this.Name = Identifier.For(name);
  15442. this.ReturnType = new TypeExpression(new Literal(TypeCode.Boolean), 0);
  15443. this.ReturnTypeExpression = new TypeExpression(new Literal(TypeCode.Boolean), 0);
  15444. }
  15445. }
  15446. public class ModelfieldContract : Node {
  15447. protected Field mf; //the modelfield this contract applies to (might be a temporary modelfield that stores unresolved override information)
  15448. protected Property ifaceMf; //the interface modelfield this contract applies to.
  15449. //invariant mf != null && ifaceMF == null || mf == null && ifaceMf != null;
  15450. public Expression Witness = null;
  15451. public bool HasExplicitWitness = false; //set to true if this modelfield has an explicitly specified witness. NOTE: Not serialized, i.e., not available in boogie!
  15452. public ExpressionList/*!*/ SatisfiesList = new ExpressionList();
  15453. public TypeNode DeclaringType;
  15454. public Member/*!*/ Modelfield { get { return this.mf == null ? (Member)this.ifaceMf : (Member)this.mf; } }
  15455. public TypeNode/*!*/ ModelfieldType { get { return this.mf == null ? this.ifaceMf.Type : this.mf.Type; } }
  15456. private bool isOverride = false;
  15457. public bool IsOverride {
  15458. //slighty complicated to work both before and after serialization, and before and after update of modelfield reference if this contract is overriding a baseclass contract.
  15459. get {
  15460. if (this.isOverride == true) return true;
  15461. return !(this.Modelfield.DeclaringType == this.DeclaringType);
  15462. }
  15463. set {
  15464. //requires value == true; (setting to false has no real meaning or effect)
  15465. isOverride = value;
  15466. }
  15467. }
  15468. private bool isSealed = false; //set to true if modelfield itself is sealed (i.e., has the keyword).
  15469. public bool IsSealed {
  15470. get { if (this.isSealed) return true;
  15471. if (this.DeclaringType == null) return false; //defensive check
  15472. return this.DeclaringType.IsSealed;
  15473. }
  15474. set { //requires value == true and the modelfield(contract) itself is sealed</summary>
  15475. this.isSealed = value; }
  15476. }
  15477. /// <summary>
  15478. /// ensures that the result is a new modelfieldcontract with an empty set of satisfies clauses and a default witness.
  15479. /// ensures that the SourceContext of the result and the default witness are set to name.SourceContext.
  15480. /// requires all attributes to be non-null
  15481. /// </summary>
  15482. public ModelfieldContract(TypeNode declaringType, AttributeList attrs, TypeNode type, Identifier name, SourceContext sctx)
  15483. : base(NodeType.ModelfieldContract)
  15484. {
  15485. this.DeclaringType = declaringType;
  15486. this.SourceContext = sctx;
  15487. if (declaringType is Class) {
  15488. this.mf = new Field(declaringType, attrs, FieldFlags.Public, name, type, null); //note: if the modelfield has an override modifier, then mf is a placeholder. This will be signalled by a 'Private' flag.
  15489. this.mf.IsModelfield = true;
  15490. this.mf.SourceContext = this.SourceContext;
  15491. } else if (declaringType is Interface) {
  15492. //Treat as a property with a getter that will return a modelfield from an implementing class
  15493. #region create a default abstract getter method getM
  15494. Method getM = new Method(declaringType, new AttributeList(), new Identifier("get_" + name.Name), new ParameterList(), type, null);
  15495. getM.SourceContext = this.SourceContext;
  15496. getM.CallingConvention = CallingConventionFlags.HasThis; //needs to be changed when we want to allow static modelfields
  15497. //Give getM [NoDefaultContract] so that it can easily be called in specs
  15498. InstanceInitializer ndCtor = SystemTypes.NoDefaultContractAttribute.GetConstructor();
  15499. if (ndCtor != null)
  15500. getM.Attributes.Add(new AttributeNode(new MemberBinding(null, ndCtor), null, AttributeTargets.Method));
  15501. //Give getM "confined" (otherwise it still can't be called in specs, as it has NoDefaultContract)
  15502. // That means make it [Pure][Reads(Reads.Owned)]
  15503. InstanceInitializer pCtor = SystemTypes.PureAttribute.GetConstructor();
  15504. if (pCtor != null)
  15505. getM.Attributes.Add(new AttributeNode(new MemberBinding(null, pCtor), null, AttributeTargets.Method));
  15506. InstanceInitializer rCtor = SystemTypes.ReadsAttribute.GetConstructor(); // can use nullary ctor since default is confined
  15507. if (rCtor != null)
  15508. getM.Attributes.Add(new AttributeNode(new MemberBinding(null, rCtor), null, AttributeTargets.Method));
  15509. //To the user, a modelfield on an interface is a field. Therefore, the user should be allowed to give it a [Rep] attribute.
  15510. //But we treat the modelfield as a property, which is not a valid target for [Rep].
  15511. //We convert a [Rep] on the property to an [Owned] on the getter.
  15512. int nrOfAttrs = (attrs == null ? 0 : attrs.Count);
  15513. for (int i = 0, j = 0; i < nrOfAttrs; i++) {
  15514. Identifier attrI = (attrs[i].Constructor as Identifier); //seems we need a HACK: Constructor has not been processed yet (by Looker).
  15515. if (i == j && attrI != null && attrI.Name == "Rep") { //test i == j for slightly improved error handling on multiple [Rep]'s
  15516. InstanceInitializer oCtor = SystemTypes.RepAttribute.GetConstructor();
  15517. if (oCtor != null) {
  15518. getM.Attributes.Add(new AttributeNode(new MemberBinding(null, oCtor), null, AttributeTargets.Method));
  15519. attrs[i] = null;
  15520. }
  15521. } else {
  15522. attrs[j] = attrs[i];
  15523. j = j + 1;
  15524. }
  15525. }
  15526. declaringType.Members.Add(getM);
  15527. getM.Flags = MethodFlags.Public | MethodFlags.Abstract | MethodFlags.NewSlot | MethodFlags.Virtual | MethodFlags.SpecialName | MethodFlags.HideBySig;
  15528. #endregion
  15529. ifaceMf = new Property(declaringType, attrs, PropertyFlags.None, name, getM, null);
  15530. ifaceMf.IsModelfield = true;
  15531. ifaceMf.SourceContext = this.SourceContext;
  15532. getM.DeclaringMember = ifaceMf;
  15533. }
  15534. }
  15535. /// <summary>
  15536. /// ensures result.Modelfield == modelfield.
  15537. /// </summary>
  15538. public ModelfieldContract(TypeNode/* ! */ declaringType, Field/* ! */ modelfield)
  15539. : base(NodeType.ModelfieldContract) {
  15540. this.DeclaringType = declaringType;
  15541. this.SourceContext = modelfield.SourceContext;
  15542. this.mf = modelfield;
  15543. if (modelfield.DeclaringType != declaringType)
  15544. this.IsOverride = true;
  15545. }
  15546. /// <summary>
  15547. /// requires this.IsOverride == true;
  15548. /// requires that newMf is a member of a superclass of mfC.DeclaringType;
  15549. /// ensures this.Modelfield == newMf;
  15550. /// this method can be used to update the modelfield of an overriding modelfieldcontract to the modelfield that is overridden.
  15551. /// </summary>
  15552. /// <param name="newMf">The overridden modelfield that this modelfieldContract applies to</param>
  15553. public void UpdateModelfield(Field newMf) {
  15554. this.mf = newMf;
  15555. }
  15556. private ModelfieldContract nearestOverriddenContract; //null when this not an overriding contract (or when getNearestContractContract has not yet been called)
  15557. /// <summary>
  15558. /// ensures: if this contract overrides a superclass contract, then result is the nearest overridden contract, else result == null.
  15559. /// </summary>
  15560. public ModelfieldContract NearestOverriddenContract {
  15561. get {
  15562. if (this.nearestOverriddenContract != null) return this.nearestOverriddenContract;
  15563. if (this.mf == null) return null; //interface modelfieldContracts can't override
  15564. if (!this.IsOverride) return null;
  15565. #region scan superclasses until nearest overriden contract is found, then return that contract.
  15566. for (Class currentClass = this.DeclaringType.BaseType as Class; currentClass != null; currentClass = currentClass.BaseClass) {
  15567. foreach (ModelfieldContract currentMfC in currentClass.Contract.ModelfieldContracts) {
  15568. if (currentMfC.Modelfield == this.mf) {
  15569. this.nearestOverriddenContract = currentMfC;
  15570. return this.nearestOverriddenContract;
  15571. }
  15572. }
  15573. }
  15574. Debug.Assert(false); //an overridden contract should have been found and returned.
  15575. return this.nearestOverriddenContract;
  15576. #endregion
  15577. }
  15578. }
  15579. }
  15580. public sealed class ModelfieldContractList {
  15581. private ModelfieldContract[]/*!*/ elements;
  15582. private int count = 0;
  15583. public ModelfieldContractList() {
  15584. this.elements = new ModelfieldContract[8];
  15585. //^ base();
  15586. }
  15587. public ModelfieldContractList(int n) {
  15588. this.elements = new ModelfieldContract[n];
  15589. //^ base();
  15590. }
  15591. public ModelfieldContractList(params ModelfieldContract[] elements) {
  15592. if (elements == null) elements = new ModelfieldContract[0];
  15593. this.elements = elements;
  15594. this.count = elements.Length;
  15595. //^ base();
  15596. }
  15597. public void Add(ModelfieldContract element) {
  15598. int n = this.elements.Length;
  15599. int i = this.count++;
  15600. if (i == n) {
  15601. int m = n * 2; if (m < 8) m = 8;
  15602. ModelfieldContract[] newElements = new ModelfieldContract[m];
  15603. for (int j = 0; j < n; j++) newElements[j] = elements[j];
  15604. this.elements = newElements;
  15605. }
  15606. this.elements[i] = element;
  15607. }
  15608. public ModelfieldContractList/*!*/ Clone() {
  15609. ModelfieldContract[] elements = this.elements;
  15610. int n = this.count;
  15611. ModelfieldContractList result = new ModelfieldContractList(n);
  15612. result.count = n;
  15613. ModelfieldContract[] newElements = result.elements;
  15614. for (int i = 0; i < n; i++)
  15615. newElements[i] = elements[i];
  15616. return result;
  15617. }
  15618. public int Count {
  15619. get { return this.count; }
  15620. set { this.count = value; }
  15621. }
  15622. [Obsolete("Use Count property instead.")]
  15623. public int Length {
  15624. get { return this.count; }
  15625. set { this.count = value; }
  15626. }
  15627. public ModelfieldContract this[int index] {
  15628. get {
  15629. return this.elements[index];
  15630. }
  15631. set {
  15632. this.elements[index] = value;
  15633. }
  15634. }
  15635. public Enumerator GetEnumerator() {
  15636. return new Enumerator(this);
  15637. }
  15638. public struct Enumerator {
  15639. private int index;
  15640. private readonly ModelfieldContractList/*!*/ list;
  15641. public Enumerator(ModelfieldContractList/*!*/ list) {
  15642. this.index = -1;
  15643. this.list = list;
  15644. }
  15645. public ModelfieldContract Current {
  15646. get {
  15647. return this.list[this.index];
  15648. }
  15649. }
  15650. public bool MoveNext() {
  15651. return ++this.index < this.list.count;
  15652. }
  15653. public void Reset() {
  15654. this.index = -1;
  15655. }
  15656. }
  15657. }
  15658. public class TypeContract : Node {
  15659. public TypeNode DeclaringType;
  15660. protected internal ModelfieldContractList modelfieldContracts;
  15661. /// <summary>
  15662. /// Deserializes attr.Expressions[i] as expression E.
  15663. /// requires attr.Expressions.Count > i;
  15664. /// requires this.DeclaringType != null;
  15665. /// </summary>
  15666. /// <returns>E if succesfull, null otherwise.</returns>
  15667. private Expression getIndexFromAttribute(AttributeNode attr, int i) {
  15668. Debug.Assert(attr != null && attr.Expressions.Count > i && this.DeclaringType != null); //something's wrong with the IL we are deserializing, should have generated an error while constructing the IL.
  15669. IContractDeserializer ds = Cci.ContractDeserializerContainer.ContractDeserializer;
  15670. if (ds == null) return null;
  15671. ds.CurrentAssembly = this.DeclaringType.DeclaringModule;
  15672. Literal l = attr.Expressions[i] as Literal;
  15673. if (l == null) return null;
  15674. string s = (string)l.Value;
  15675. return ds.ParseContract(this, s, null);
  15676. }
  15677. /// <summary>
  15678. /// requires attr.Expressions.Count > 0
  15679. /// ensures if attr.Expressions[0] can be deserialized as modelfield F, then:
  15680. /// if F key in contractLookup, then returns matching value, else returns new ModelfieldContract mfC for F
  15681. /// else returns null
  15682. /// ensures if new mfC created, then (F, mfC) in contractLookup and mfC in this.ModelfieldContracts
  15683. /// </summary>
  15684. private ModelfieldContract getContractFor(AttributeNode attr, Dictionary<Field, ModelfieldContract> contractLookup) {
  15685. Expression mfBinding = this.getIndexFromAttribute(attr, 0);
  15686. //extract modelfield from mfBinding
  15687. if (!(mfBinding is MemberBinding)) return null;
  15688. Field modelfield = (mfBinding as MemberBinding).BoundMember as Field;
  15689. if (modelfield == null) return null;
  15690. //If this modelfield does not yet have a contract, then create one now and add <modelfield,mfC> to createdContracts
  15691. ModelfieldContract mfC = null;
  15692. if (!contractLookup.TryGetValue(modelfield, out mfC)) {
  15693. mfC = new ModelfieldContract(this.DeclaringType, modelfield);
  15694. this.modelfieldContracts.Add(mfC);
  15695. contractLookup.Add(modelfield, mfC);
  15696. }
  15697. return mfC;
  15698. }
  15699. public ModelfieldContractList/*!*/ ModelfieldContracts {
  15700. get {
  15701. if (this.modelfieldContracts == null) {
  15702. this.modelfieldContracts = new ModelfieldContractList();
  15703. #region deserialize the modelfieldcontracts if needed
  15704. Dictionary<Field,ModelfieldContract> createdContracts = new Dictionary<Field,ModelfieldContract>(); //key = modelfield memberbinding, value = contract for that modelfield (if one was created already)
  15705. if (this.DeclaringType != null) {
  15706. foreach (AttributeNode attr in this.DeclaringType.Attributes) {
  15707. if (attr == null) continue;
  15708. MemberBinding mb = attr.Constructor as MemberBinding;
  15709. if (mb == null || mb.BoundMember == null) continue;
  15710. if (mb.BoundMember.DeclaringType == SystemTypes.ModelfieldContractAttribute) {
  15711. ModelfieldContract mfC = this.getContractFor(attr, createdContracts);
  15712. Expression witness = this.getIndexFromAttribute(attr, 1);
  15713. if (witness == null) continue;
  15714. witness.SourceContext = MethodContract.GetSourceContext(attr);
  15715. mfC.Witness = witness;
  15716. } else if (mb.BoundMember.DeclaringType == SystemTypes.SatisfiesAttribute) {
  15717. ModelfieldContract mfC = this.getContractFor(attr, createdContracts);
  15718. Expression satClause = this.getIndexFromAttribute(attr, 1);
  15719. if (satClause == null) continue;
  15720. satClause.SourceContext = MethodContract.GetSourceContext(attr);
  15721. mfC.SatisfiesList.Add(satClause);
  15722. }
  15723. }
  15724. }
  15725. #endregion
  15726. }
  15727. return this.modelfieldContracts;
  15728. }
  15729. set { this.modelfieldContracts = value; }
  15730. }
  15731. public InvariantList InheritedInvariants;
  15732. protected internal InvariantList invariants;
  15733. public InvariantList Invariants{
  15734. get{
  15735. if (this.invariants != null) return this.invariants;
  15736. InvariantList invs = this.invariants = new InvariantList();
  15737. if (this.DeclaringType != null){
  15738. AttributeList attributes = this.DeclaringType.Attributes;
  15739. IContractDeserializer ds = Cci.ContractDeserializerContainer.ContractDeserializer;
  15740. if (ds != null){
  15741. Module savedCurrentAssembly = ds.CurrentAssembly;
  15742. ds.CurrentAssembly = this.DeclaringType == null ? null : this.DeclaringType.DeclaringModule;
  15743. for (int i = 0, n = attributes == null || attributes.Count == 0 ? 0 : attributes.Count; i < n; i++){
  15744. AttributeNode attr = attributes[i];
  15745. if (attr == null) continue;
  15746. MemberBinding mb = attr.Constructor as MemberBinding;
  15747. if (mb != null){
  15748. if (mb.BoundMember == null) continue;
  15749. if (mb.BoundMember.DeclaringType != SystemTypes.InvariantAttribute) continue;
  15750. if (attr.Expressions == null || !(attr.Expressions.Count > 0)) continue;
  15751. Literal l = attr.Expressions[0] as Literal;
  15752. if (l == null) continue;
  15753. string s = (string) l.Value;
  15754. Expression e = ds.ParseContract(this,s,null);
  15755. if (e != null){
  15756. Invariant inv = new Invariant(this.DeclaringType,null,Identifier.For("invariant"+i));
  15757. SourceContext ctx = MethodContract.GetSourceContext(attr);
  15758. inv.SourceContext = ctx;
  15759. inv.Condition = e;
  15760. invs.Add(inv);
  15761. }
  15762. }
  15763. }
  15764. // Make the type contract look as it does when the type is compiled from source
  15765. this.FramePropertyGetter = this.DeclaringType.GetMethod(Identifier.For("get_SpecSharp::FrameGuard"), null);
  15766. this.InitFrameSetsMethod = this.DeclaringType.GetMethod(Identifier.For("SpecSharp::InitGuardSets"), null);
  15767. this.InvariantMethod = this.DeclaringType.GetMethod(Identifier.For("SpecSharp::CheckInvariant"), CoreSystemTypes.Boolean);
  15768. this.FrameProperty = this.DeclaringType.GetProperty(Identifier.For("SpecSharp::FrameGuard"));
  15769. this.FrameField = this.DeclaringType.GetField(Identifier.For("SpecSharp::frameGuard"));
  15770. ds.CurrentAssembly = savedCurrentAssembly;
  15771. }
  15772. }
  15773. return this.invariants;
  15774. }
  15775. set{
  15776. this.invariants = value;
  15777. }
  15778. }
  15779. // when non-null, points to the method added to the DeclaringType that will have the invariants in its body
  15780. // needed so when each invariant is visited, the proper environment can be set up for it.
  15781. // NB: Dont' visit it as part of StandardVisitor
  15782. public Field FrameField;
  15783. public Property FrameProperty;
  15784. public Method FramePropertyGetter;
  15785. public Method InitFrameSetsMethod;
  15786. public Method InvariantMethod;// when non-null, points to the method added to the DeclaringType that will have the invariants in its body
  15787. /// <summary>
  15788. /// Microsoft.Contracts.FrameGuardGetter implementation for this class.
  15789. /// </summary>
  15790. public Method GetFrameGuardMethod;
  15791. /// <summary>
  15792. /// When types get constructed via the Reader, we let the Invariants be initialized on demand.
  15793. /// When the parser creates a type, we want the type contract to contain the empty invariant list
  15794. /// so that it won't grovel through the attributes on first access to Invariants.
  15795. /// </summary>
  15796. /// <param name="containingType"></param>
  15797. public TypeContract(TypeNode containingType) : this(containingType, false)
  15798. {
  15799. }
  15800. public TypeContract(TypeNode containingType, bool initInvariantList)
  15801. : base(NodeType.TypeContract) {
  15802. this.DeclaringType = containingType;
  15803. if (initInvariantList) {
  15804. this.invariants = new InvariantList();
  15805. }
  15806. }
  15807. public int InvariantCount { get { return Invariants == null ? 0 : Invariants.Count; } }
  15808. public int ModelfieldContractCount { get { return ModelfieldContracts == null ? 0 : ModelfieldContracts.Count; } }
  15809. }
  15810. public interface IContractDeserializer{
  15811. // when text is a requires, ensures, or modifies
  15812. Expression ParseContract(MethodContract mc, string text, ErrorNodeList errors);
  15813. // when text is an assertion or an assume in code
  15814. Expression ParseContract(Method m, string text, ErrorNodeList errs);
  15815. // when text is an invariant
  15816. Expression ParseContract(TypeContract/*!*/ tc, string text, ErrorNodeList errs);
  15817. Module CurrentAssembly { get; set; }
  15818. ErrorNodeList ErrorList { get; set; }
  15819. }
  15820. #endif
  15821. public class Method : Member{
  15822. #if ExtendedRuntime
  15823. /// <summary>
  15824. /// Gets the first attribute of the given type in the attribute list of this method, or in the attribute list
  15825. /// of the method's declaring member (if it exists).
  15826. /// Returns null if none found.
  15827. /// This should not be called until the AST containing this member has been processed to replace symbolic references
  15828. /// to members with references to the actual members.
  15829. /// </summary>
  15830. public virtual AttributeNode GetAttributeFromSelfOrDeclaringMember (TypeNode attributeType) {
  15831. AttributeNode a = base.GetAttribute(attributeType);
  15832. if (a == null && this.DeclaringMember != null) {
  15833. a = this.DeclaringMember.GetAttribute(attributeType);
  15834. }
  15835. return a;
  15836. }
  15837. #endif
  15838. #if ExtendedRuntime
  15839. protected internal MethodContract/*?*/ contract;
  15840. internal static readonly MethodContract/*!*/ DummyContract = new MethodContract(null);
  15841. /// <summary>The preconditions, postconditions, and modifies clauses of this method.</summary>
  15842. public virtual MethodContract/*?*/ Contract {
  15843. get {
  15844. if (contract != null) return contract == Method.DummyContract ? null : contract;
  15845. // There may be serialized contracts in the method's attributes.
  15846. MethodContract mc = new MethodContract(this);
  15847. // Pull on the properties to see if anything shows up
  15848. int count = mc.Requires.Count;
  15849. count += mc.Ensures.Count;
  15850. count += mc.Modifies.Count;
  15851. count += (mc.IsPure) ? 1 : 0;
  15852. if (0 < count) { contract = mc; return contract; } else { contract = Method.DummyContract; return null; }
  15853. }
  15854. set {
  15855. contract = value;
  15856. if (value != null) {
  15857. contract.DeclaringMethod = this;
  15858. }
  15859. }
  15860. }
  15861. #endif
  15862. #if !MinimalReader
  15863. public TypeNodeList ImplementedTypes;
  15864. public TypeNodeList ImplementedTypeExpressions;
  15865. public bool HasCompilerGeneratedSignature = true;
  15866. public TypeNode ReturnTypeExpression;
  15867. /// <summary>Provides a way to retrieve the parameters and local variables defined in this method given their names.</summary>
  15868. public MethodScope Scope;
  15869. public bool HasOutOfBandContract = false;
  15870. protected TrivialHashtable/*!*/ Locals = new TrivialHashtable();
  15871. #endif
  15872. #if !FxCop
  15873. public LocalList LocalList;
  15874. protected SecurityAttributeList securityAttributes;
  15875. /// <summary>Contains declarative security information associated with the type.</summary>
  15876. public SecurityAttributeList SecurityAttributes {
  15877. get {
  15878. if (this.securityAttributes != null) return this.securityAttributes;
  15879. if (this.attributes == null) {
  15880. AttributeList al = this.Attributes; //Getting the type attributes also gets the security attributes, in the case of a type that was read in by the Reader
  15881. if (al != null) al = null;
  15882. if (this.securityAttributes != null) return this.securityAttributes;
  15883. }
  15884. return this.securityAttributes = new SecurityAttributeList(0);
  15885. }
  15886. set {
  15887. this.securityAttributes = value;
  15888. }
  15889. }
  15890. #else
  15891. internal SecurityAttributeList securityAttributes;
  15892. public SecurityAttributeList SecurityAttributes{
  15893. get{return this.securityAttributes;}
  15894. internal set{this.securityAttributes = value;}
  15895. }
  15896. private LocalCollection locals;
  15897. public LocalCollection Locals{
  15898. get{
  15899. if (locals == null) this.Body = this.Body;
  15900. return this.locals;
  15901. }
  15902. internal set {
  15903. this.locals = value;
  15904. }
  15905. }
  15906. /// <summary>
  15907. /// Gets a value indicating whether the method is a property or event accessor.
  15908. /// </summary>
  15909. /// <value>
  15910. /// <see langword="true"/> if the <see cref="Method"/> is a property or event
  15911. /// accessor; otherwise, <see langword="false"/>.
  15912. /// </value>
  15913. /// <remarks>
  15914. /// <see cref="IsAccessor"/> returns <see langword="true"/> if
  15915. /// <see cref="DeclaringMember"/> is not <see langword="null"/>.
  15916. /// </remarks>
  15917. public bool IsAccessor{
  15918. get{return this.declaringMember != null;}
  15919. }
  15920. internal static bool EnforceMethodRepresentationCreationPolicy;
  15921. internal static int PopulatedBodiesCount;
  15922. internal static int PopulatedInstructionsCount;
  15923. #endif
  15924. public delegate void MethodBodyProvider(Method/*!*/ method, object/*!*/ handle, bool asInstructionList);
  15925. public MethodBodyProvider ProvideBody;
  15926. public object ProviderHandle; //Opaque information to be used by the method body provider
  15927. #if ILOFFSETS
  15928. public readonly int MethodToken;
  15929. public Method(MethodBodyProvider provider, object handle, int methodToken)
  15930. : this(provider, handle)
  15931. {
  15932. this.MethodToken = methodToken;
  15933. }
  15934. #endif
  15935. public Method()
  15936. : base(NodeType.Method){
  15937. }
  15938. public Method(MethodBodyProvider provider, object handle)
  15939. : base(NodeType.Method){
  15940. this.ProvideBody = provider;
  15941. this.ProviderHandle = handle;
  15942. }
  15943. public Method(TypeNode declaringType, AttributeList attributes, Identifier name, ParameterList parameters, TypeNode returnType, Block body)
  15944. : base(declaringType, attributes, name, NodeType.Method){
  15945. this.body = body;
  15946. this.Parameters = parameters; // important to use setter here.
  15947. this.returnType = returnType;
  15948. }
  15949. private MethodFlags flags;
  15950. public MethodFlags Flags{
  15951. get{return this.flags;}
  15952. set{this.flags = value;}
  15953. }
  15954. private MethodImplFlags implFlags;
  15955. public MethodImplFlags ImplFlags{
  15956. get{return this.implFlags;}
  15957. set{this.implFlags = value;}
  15958. }
  15959. private MethodList implementedInterfaceMethods;
  15960. public MethodList ImplementedInterfaceMethods{
  15961. get{return this.implementedInterfaceMethods;}
  15962. set{this.implementedInterfaceMethods = value;}
  15963. }
  15964. #if !MinimalReader
  15965. private MethodList implicitlyImplementedInterfaceMethods;
  15966. /// <summary>
  15967. /// Computes the implicitly implemented methods for any method, not necessarily being compiled.
  15968. /// </summary>
  15969. public MethodList ImplicitlyImplementedInterfaceMethods{
  15970. get{
  15971. if (this.implicitlyImplementedInterfaceMethods == null){
  15972. this.implicitlyImplementedInterfaceMethods = new MethodList();
  15973. // There are several reasons that this method cannot implicitly implement any interface method.
  15974. if ((this.ImplementedInterfaceMethods == null || this.ImplementedInterfaceMethods.Count == 0) && this.IsPublic && !this.IsStatic){
  15975. // It can implicitly implement an interface method for those interfaces that
  15976. // the method's type explicitly declares it implements
  15977. if (this.DeclaringType != null && this.DeclaringType.Interfaces != null){
  15978. foreach (Interface i in this.DeclaringType.Interfaces){
  15979. if (i == null) continue;
  15980. Method match = i.GetMatchingMethod(this);
  15981. // But it cannot implicitly implement an interface method if there is
  15982. // an explicit implementation in the same type.
  15983. if (match != null && match.ReturnType == this.ReturnType && !this.DeclaringType.ImplementsExplicitly(match))
  15984. this.implicitlyImplementedInterfaceMethods.Add(match);
  15985. }
  15986. }
  15987. // It can implicitly implement an interface method if it overrides a base class
  15988. // method and *that* method implicitly implements the interface method.
  15989. // (Note: if this method's type does *not* explicitly declare that it implements
  15990. // the interface, then unless the method overrides a method that does, it is *not*
  15991. // used as an implicit implementation.)
  15992. if (this.OverriddenMethod != null){
  15993. foreach (Method method in this.OverriddenMethod.ImplicitlyImplementedInterfaceMethods)
  15994. // But it cannot implicitly implement an interface method if there is
  15995. // an explicit implementation in the same type.
  15996. if (!this.DeclaringType.ImplementsExplicitly(method)) {
  15997. int i = 0;
  15998. int n = this.implicitlyImplementedInterfaceMethods.Count;
  15999. while (i < n) {
  16000. Method alreadyImplementedMethod = this.implicitlyImplementedInterfaceMethods[i];
  16001. if (alreadyImplementedMethod == method) break; // don't add it twice
  16002. i++;
  16003. }
  16004. if (i == n)
  16005. this.implicitlyImplementedInterfaceMethods.Add(method);
  16006. }
  16007. }
  16008. }
  16009. }
  16010. return this.implicitlyImplementedInterfaceMethods;
  16011. }
  16012. set {
  16013. this.implicitlyImplementedInterfaceMethods = value;
  16014. }
  16015. }
  16016. #endif
  16017. private CallingConventionFlags callingConvention;
  16018. public CallingConventionFlags CallingConvention{
  16019. get{return this.callingConvention;}
  16020. set{this.callingConvention = value;}
  16021. }
  16022. private bool initLocals = true;
  16023. /// <summary>True if all local variables are to be initialized to default values before executing the method body.</summary>
  16024. public bool InitLocals{
  16025. get{return this.initLocals;}
  16026. set{this.initLocals = value;}
  16027. }
  16028. private bool isGeneric;
  16029. /// <summary>True if this method is a template that conforms to the rules for a CLR generic method.</summary>
  16030. public bool IsGeneric{
  16031. get{return this.isGeneric;}
  16032. set{this.isGeneric = value;}
  16033. }
  16034. private ParameterList parameters;
  16035. /// <summary>The parameters this method has to be called with.</summary>
  16036. public ParameterList Parameters{
  16037. get{return this.parameters;}
  16038. set{
  16039. this.parameters = value;
  16040. if (value != null) {
  16041. for (int i = 0, n = value.Count; i < n; i++) {
  16042. Parameter par = parameters[i];
  16043. if (par == null) continue;
  16044. par.DeclaringMethod = this;
  16045. }
  16046. }
  16047. }
  16048. }
  16049. private PInvokeFlags pInvokeFlags = PInvokeFlags.None;
  16050. public PInvokeFlags PInvokeFlags{
  16051. get{return this.pInvokeFlags;}
  16052. set{this.pInvokeFlags = value;}
  16053. }
  16054. private Module pInvokeModule;
  16055. public Module PInvokeModule{
  16056. get{return this.pInvokeModule;}
  16057. set{this.pInvokeModule = value;}
  16058. }
  16059. private string pInvokeImportName;
  16060. public string PInvokeImportName{
  16061. get{return this.pInvokeImportName;}
  16062. set{this.pInvokeImportName = value;}
  16063. }
  16064. private AttributeList returnAttributes;
  16065. /// <summary>Attributes that apply to the return value of this method.</summary>
  16066. public AttributeList ReturnAttributes{
  16067. get{return this.returnAttributes;}
  16068. set{this.returnAttributes = value;}
  16069. }
  16070. private MarshallingInformation returnTypeMarshallingInformation;
  16071. public MarshallingInformation ReturnTypeMarshallingInformation{
  16072. get{return this.returnTypeMarshallingInformation;}
  16073. set{this.returnTypeMarshallingInformation = value;}
  16074. }
  16075. private TypeNode returnType;
  16076. /// <summary>The type of value that this method may return.</summary>
  16077. public TypeNode ReturnType{
  16078. get{return this.returnType;}
  16079. set{this.returnType = value;}
  16080. }
  16081. private Member declaringMember;
  16082. /// <summary>Provides the declaring event or property of an accessor.</summary>
  16083. public Member DeclaringMember{
  16084. get{
  16085. if (this.declaringMember == null && this.DeclaringType != null && !this.DeclaringType.membersBeingPopulated) {
  16086. MemberList dummyMembers = this.DeclaringType.Members; //evaluate for side effect of filling in declaringMember
  16087. }
  16088. return this.declaringMember;
  16089. }
  16090. set{this.declaringMember = value;}
  16091. }
  16092. private This thisParameter;
  16093. public This ThisParameter{
  16094. get{
  16095. if (this.thisParameter == null && !this.IsStatic && this.DeclaringType != null) {
  16096. if (this.DeclaringType.IsValueType)
  16097. this.ThisParameter = new This(this.DeclaringType.GetReferenceType());
  16098. else
  16099. this.ThisParameter = new This(this.DeclaringType);
  16100. }
  16101. return this.thisParameter;
  16102. }
  16103. set{
  16104. if (value != null) value.DeclaringMethod = this;
  16105. this.thisParameter = value;
  16106. }
  16107. }
  16108. protected internal Block body;
  16109. /// <summary>The instructions constituting the body of this method, in the form of a tree.</summary>
  16110. public virtual Block Body{
  16111. get{
  16112. if (this.body != null) return this.body;
  16113. if (this.ProvideBody != null && this.ProviderHandle != null){
  16114. lock (Module.GlobalLock){
  16115. if (this.body == null){
  16116. this.ProvideBody(this, this.ProviderHandle, false);
  16117. #if FxCop
  16118. if (EnforceMethodRepresentationCreationPolicy && this.body.Statements.Count > 0)
  16119. System.Threading.Interlocked.Increment(ref Method.PopulatedBodiesCount);
  16120. #endif
  16121. }
  16122. }
  16123. }
  16124. return this.body;
  16125. }
  16126. set{
  16127. #if FxCop
  16128. if (EnforceMethodRepresentationCreationPolicy && value == null && this.body != null && this.body.Statements.Count > 0)
  16129. System.Threading.Interlocked.Decrement(ref Method.PopulatedBodiesCount);
  16130. #endif
  16131. this.body = value;
  16132. }
  16133. }
  16134. /// <summary>
  16135. /// A delegate that is called the first time Attributes is accessed, if non-null.
  16136. /// Provides for incremental construction of the type node.
  16137. /// Must not leave Attributes null.
  16138. /// </summary>
  16139. public MethodAttributeProvider ProvideMethodAttributes;
  16140. /// <summary>
  16141. /// The type of delegates that fill in the Attributes property of the given method.
  16142. /// </summary>
  16143. public delegate void MethodAttributeProvider(Method/*!*/ method, object/*!*/ handle);
  16144. public override AttributeList Attributes {
  16145. get{
  16146. if (this.attributes == null){
  16147. if (this.ProvideMethodAttributes != null && this.ProviderHandle != null){
  16148. lock (Module.GlobalLock){
  16149. if (this.attributes == null)
  16150. this.ProvideMethodAttributes(this, this.ProviderHandle);
  16151. }
  16152. }else
  16153. this.attributes = new AttributeList(0);
  16154. }
  16155. return this.attributes;
  16156. }
  16157. set{
  16158. this.attributes = value;
  16159. }
  16160. }
  16161. #if FxCop
  16162. internal void ClearBody(){
  16163. #else
  16164. public void ClearBody(){
  16165. #endif
  16166. lock(Module.GlobalLock){
  16167. this.Body = null;
  16168. this.Instructions = null;
  16169. #if !FxCop
  16170. this.LocalList = null;
  16171. #else
  16172. this.Locals = null;
  16173. #endif
  16174. }
  16175. }
  16176. protected string conditionalSymbol;
  16177. protected bool doesNotHaveAConditionalSymbol;
  16178. public string ConditionalSymbol{
  16179. get{
  16180. if (this.doesNotHaveAConditionalSymbol) return null;
  16181. if (this.conditionalSymbol == null){
  16182. lock (this){
  16183. if (this.conditionalSymbol != null) return this.conditionalSymbol;
  16184. AttributeNode condAttr = this.GetAttribute(SystemTypes.ConditionalAttribute);
  16185. if (condAttr != null && condAttr.Expressions != null && condAttr.Expressions.Count > 0){
  16186. Literal lit = condAttr.Expressions[0] as Literal;
  16187. if (lit != null){
  16188. this.conditionalSymbol = lit.Value as string;
  16189. if (this.conditionalSymbol != null) return this.conditionalSymbol;
  16190. }
  16191. }
  16192. this.doesNotHaveAConditionalSymbol = true;
  16193. }
  16194. }
  16195. return this.conditionalSymbol;
  16196. }
  16197. set{
  16198. this.conditionalSymbol = value;
  16199. }
  16200. }
  16201. protected InstructionList instructions;
  16202. /// <summary>The instructions constituting the body of this method, in the form of a linear list of Instruction nodes.</summary>
  16203. public virtual InstructionList Instructions{
  16204. get{
  16205. if (this.instructions != null) return this.instructions;
  16206. if (this.ProvideBody != null && this.ProviderHandle != null){
  16207. lock (Module.GlobalLock){
  16208. if (this.instructions == null){
  16209. this.ProvideBody(this, this.ProviderHandle, true);
  16210. #if FxCop
  16211. if (EnforceMethodRepresentationCreationPolicy)
  16212. System.Threading.Interlocked.Increment(ref Method.PopulatedInstructionsCount);
  16213. #endif
  16214. }
  16215. }
  16216. }
  16217. return this.instructions;
  16218. }
  16219. set{
  16220. #if FxCop
  16221. if (EnforceMethodRepresentationCreationPolicy && this.instructions != null && value == null)
  16222. System.Threading.Interlocked.Decrement(ref Method.PopulatedInstructionsCount);
  16223. #endif
  16224. this.instructions = value;
  16225. }
  16226. }
  16227. #if !FxCop
  16228. protected ExceptionHandlerList exceptionHandlers;
  16229. public virtual ExceptionHandlerList ExceptionHandlers{
  16230. get{
  16231. if (this.exceptionHandlers != null) return this.exceptionHandlers;
  16232. Block dummy = this.Body;
  16233. if (this.exceptionHandlers == null) this.exceptionHandlers = new ExceptionHandlerList(0);
  16234. return this.exceptionHandlers;
  16235. }
  16236. set{
  16237. this.exceptionHandlers = value;
  16238. }
  16239. }
  16240. #endif
  16241. #if !NoXml
  16242. protected override Identifier GetDocumentationId(){
  16243. if (this.Template != null) return this.Template.GetDocumentationId();
  16244. StringBuilder sb = new StringBuilder(this.DeclaringType.DocumentationId.ToString());
  16245. sb[0] = 'M';
  16246. sb.Append('.');
  16247. if (this.NodeType == NodeType.InstanceInitializer)
  16248. sb.Append("#ctor");
  16249. else if (this.Name != null){
  16250. sb.Append(this.Name.ToString());
  16251. if (TargetPlatform.GenericTypeNamesMangleChar != 0 && this.TemplateParameters != null && this.TemplateParameters.Count > 0) {
  16252. sb.Append(TargetPlatform.GenericTypeNamesMangleChar);
  16253. sb.Append(TargetPlatform.GenericTypeNamesMangleChar);
  16254. sb.Append(this.TemplateParameters.Count);
  16255. }
  16256. }
  16257. ParameterList parameters = this.Parameters;
  16258. for (int i = 0, n = parameters == null ? 0 : parameters.Count; i < n; i++){
  16259. Parameter par = parameters[i];
  16260. if (par == null || par.Type == null) continue;
  16261. if (i == 0)
  16262. sb.Append('(');
  16263. else
  16264. sb.Append(',');
  16265. par.Type.AppendDocumentIdMangledName(sb, this.TemplateParameters, this.DeclaringType.TemplateParameters);
  16266. if (i == n-1)
  16267. sb.Append(')');
  16268. }
  16269. if (this.IsSpecialName && this.ReturnType != null && this.Name != null &&
  16270. (this.Name.UniqueIdKey == StandardIds.opExplicit.UniqueIdKey || this.Name.UniqueIdKey == StandardIds.opImplicit.UniqueIdKey)){
  16271. sb.Append('~');
  16272. this.ReturnType.AppendDocumentIdMangledName(sb, this.TemplateParameters, this.DeclaringType.TemplateParameters);
  16273. }
  16274. return Identifier.For(sb.ToString());
  16275. }
  16276. #endif
  16277. protected internal string fullName;
  16278. public override string/*!*/ FullName {
  16279. get{
  16280. if (this.fullName != null) return this.fullName;
  16281. StringBuilder sb = new StringBuilder();
  16282. if (this.DeclaringType != null) {
  16283. sb.Append(this.DeclaringType.FullName);
  16284. sb.Append('.');
  16285. if (this.NodeType == NodeType.InstanceInitializer)
  16286. sb.Append("#ctor");
  16287. else if (this.Name != null)
  16288. sb.Append(this.Name.ToString());
  16289. ParameterList parameters = this.Parameters;
  16290. for (int i = 0, n = parameters == null ? 0 : parameters.Count; i < n; i++) {
  16291. Parameter par = parameters[i];
  16292. if (par == null || par.Type == null) continue;
  16293. if (i == 0)
  16294. sb.Append('(');
  16295. else
  16296. sb.Append(',');
  16297. sb.Append(par.Type.FullName);
  16298. if (i == n - 1)
  16299. sb.Append(')');
  16300. }
  16301. }
  16302. return this.fullName = sb.ToString();
  16303. }
  16304. }
  16305. #if ExtendedRuntime
  16306. public override string HelpText {
  16307. get {
  16308. if (this.helpText != null)
  16309. return this.helpText;
  16310. StringBuilder sb = new StringBuilder(base.HelpText);
  16311. // if there is already some help text, start the contract on a new line
  16312. bool startWithNewLine = (sb.Length != 0);
  16313. if (this.Contract != null){
  16314. MethodContract mc = this.Contract;
  16315. RequiresList rs = mc.Requires;
  16316. if (rs != null && rs.Count == 0) { mc.Requires = null; rs = mc.Requires; }
  16317. for (int i = 0, n = rs == null ? 0 : rs.Count; i < n; i++){
  16318. Requires r = rs[i];
  16319. if (r == null) continue;
  16320. Expression e = r.Condition;
  16321. if (e.SourceContext.StartPos < e.SourceContext.EndPos && e.SourceContext.SourceText != ""){
  16322. if (startWithNewLine) sb.Append('\n');
  16323. sb.Append("requires ");
  16324. sb.Append(e.SourceContext.SourceText);
  16325. sb.Append(";");
  16326. startWithNewLine = true;
  16327. }
  16328. }
  16329. EnsuresList es = mc.Ensures;
  16330. if (es != null && es.Count == 0) { mc.Ensures = null; es = mc.Ensures; }
  16331. if (es != null) {
  16332. for (int i = 0, n = es.Count; i < n; i++) {
  16333. Ensures e = es[i];
  16334. if (e == null) continue;
  16335. if (startWithNewLine) sb.Append('\n');
  16336. EnsuresExceptional ee = e as EnsuresExceptional;
  16337. if (ee != null) {
  16338. sb.Append("throws ");
  16339. if (ee.Variable != null) { sb.Append("("); }
  16340. sb.Append(ee.Type.Name.ToString());
  16341. if (ee.Variable != null) {
  16342. sb.Append(" ");
  16343. sb.Append(ee.Variable.SourceContext.SourceText);
  16344. sb.Append(")");
  16345. }
  16346. }
  16347. if (e.PostCondition != null) {
  16348. if (ee != null) {
  16349. sb.Append(" ");
  16350. }
  16351. Expression cond = e.PostCondition;
  16352. sb.Append("ensures ");
  16353. sb.Append(cond.SourceContext.SourceText);
  16354. }
  16355. sb.Append(";");
  16356. startWithNewLine = true;
  16357. }
  16358. }
  16359. ExpressionList exps = mc.Modifies;
  16360. // Force deserialization in case that is needed
  16361. if (exps != null && exps.Count == 0) { mc.Modifies = null; exps = mc.Modifies; }
  16362. if (exps != null) {
  16363. for (int i = 0, n = exps.Count; i < n; i++) {
  16364. Expression mod = exps[i];
  16365. if (mod != null && mod.SourceContext.StartPos < mod.SourceContext.EndPos && mod.SourceContext.SourceText != "") {
  16366. if (startWithNewLine) sb.Append('\n');
  16367. sb.Append("modifies ");
  16368. sb.Append(mod.SourceContext.SourceText);
  16369. sb.Append(";");
  16370. startWithNewLine = true;
  16371. }
  16372. }
  16373. }
  16374. }
  16375. return this.helpText = sb.ToString();
  16376. }
  16377. set {
  16378. base.HelpText = value;
  16379. }
  16380. }
  16381. #endif
  16382. public virtual string GetUnmangledNameWithoutTypeParameters(){
  16383. return this.GetUnmangledNameWithoutTypeParameters(false);
  16384. }
  16385. public virtual string GetUnmangledNameWithoutTypeParameters(bool omitParameterTypes){
  16386. StringBuilder sb = new StringBuilder();
  16387. if (this.NodeType == NodeType.InstanceInitializer)
  16388. sb.Append("#ctor");
  16389. else if (this.Name != null) {
  16390. string name = this.Name.ToString();
  16391. int lastDot = name.LastIndexOf('.');
  16392. int lastMangle = name.LastIndexOf('>');
  16393. // explicit interface method overrides will have typenames in
  16394. // their method name, which may also contain type parameters
  16395. if (lastMangle < lastDot)
  16396. lastMangle = -1;
  16397. if (lastMangle > 0)
  16398. sb.Append(name.Substring(0, lastMangle+1));
  16399. else
  16400. sb.Append(name);
  16401. }
  16402. if (omitParameterTypes) return sb.ToString();
  16403. ParameterList parameters = this.Parameters;
  16404. for (int i = 0, n = parameters == null ? 0 : parameters.Count; i < n; i++) {
  16405. Parameter par = parameters[i];
  16406. if (par == null || par.Type == null) continue;
  16407. if (i == 0)
  16408. sb.Append('(');
  16409. else
  16410. sb.Append(',');
  16411. sb.Append(par.Type.GetFullUnmangledNameWithTypeParameters());
  16412. if (i == n - 1) {
  16413. #if !MinimalReader
  16414. if (this.IsVarArg) {
  16415. sb.Append(", __arglist");
  16416. }
  16417. #endif
  16418. sb.Append(')');
  16419. }
  16420. }
  16421. return sb.ToString();
  16422. }
  16423. public virtual string GetUnmangledNameWithTypeParameters(){
  16424. return this.GetUnmangledNameWithTypeParameters(false);
  16425. }
  16426. public virtual string GetUnmangledNameWithTypeParameters(bool omitParameterTypes){
  16427. StringBuilder sb = new StringBuilder();
  16428. sb.Append(this.GetUnmangledNameWithoutTypeParameters(true));
  16429. TypeNodeList templateParameters = this.TemplateParameters;
  16430. for (int i = 0, n = templateParameters == null ? 0 : templateParameters.Count; i < n; i++){
  16431. TypeNode tpar = templateParameters[i];
  16432. if (tpar == null) continue;
  16433. if (i == 0)
  16434. sb.Append('<');
  16435. else
  16436. sb.Append(',');
  16437. sb.Append(tpar.Name.ToString());
  16438. if (i == n-1)
  16439. sb.Append('>');
  16440. }
  16441. if (omitParameterTypes) return sb.ToString();
  16442. ParameterList parameters = this.Parameters;
  16443. for (int i = 0, n = parameters == null ? 0 : parameters.Count; i < n; i++){
  16444. Parameter par = parameters[i];
  16445. if (par == null || par.Type == null) continue;
  16446. if (i == 0)
  16447. sb.Append('(');
  16448. else
  16449. sb.Append(',');
  16450. sb.Append(par.Type.GetFullUnmangledNameWithTypeParameters());
  16451. if (i == n-1)
  16452. sb.Append(')');
  16453. }
  16454. return sb.ToString();
  16455. }
  16456. public virtual string GetFullUnmangledNameWithTypeParameters(){
  16457. return this.GetFullUnmangledNameWithTypeParameters(false);
  16458. }
  16459. public virtual string GetFullUnmangledNameWithTypeParameters(bool omitParameterTypes){
  16460. StringBuilder sb = new StringBuilder();
  16461. sb.Append(this.DeclaringType.GetFullUnmangledNameWithTypeParameters());
  16462. sb.Append('.');
  16463. sb.Append(this.GetUnmangledNameWithTypeParameters());
  16464. return sb.ToString();
  16465. }
  16466. public static MethodFlags GetVisibilityUnion(Method m1, Method m2){
  16467. if (m1 == null && m2 != null) return m2.Flags & MethodFlags.MethodAccessMask;
  16468. if (m2 == null && m1 != null) return m1.Flags & MethodFlags.MethodAccessMask;
  16469. if (m1 == null || m2 == null) return MethodFlags.CompilerControlled;
  16470. return Method.GetVisibilityUnion(m1.Flags, m2.Flags);
  16471. }
  16472. public static MethodFlags GetVisibilityUnion(MethodFlags vis1, MethodFlags vis2){
  16473. vis1 &= MethodFlags.MethodAccessMask;
  16474. vis2 &= MethodFlags.MethodAccessMask;
  16475. switch (vis1){
  16476. case MethodFlags.Public:
  16477. return MethodFlags.Public;
  16478. case MethodFlags.Assembly:
  16479. switch (vis2){
  16480. case MethodFlags.Public:
  16481. return MethodFlags.Public;
  16482. case MethodFlags.FamORAssem:
  16483. case MethodFlags.Family:
  16484. return MethodFlags.FamORAssem;
  16485. default:
  16486. return vis1;
  16487. }
  16488. case MethodFlags.FamANDAssem:
  16489. switch (vis2){
  16490. case MethodFlags.Public:
  16491. return MethodFlags.Public;
  16492. case MethodFlags.Assembly:
  16493. return MethodFlags.Assembly;
  16494. case MethodFlags.FamORAssem:
  16495. return MethodFlags.FamORAssem;
  16496. case MethodFlags.Family:
  16497. return MethodFlags.Family;
  16498. default:
  16499. return vis1;
  16500. }
  16501. case MethodFlags.FamORAssem:
  16502. switch (vis2){
  16503. case MethodFlags.Public:
  16504. return MethodFlags.Public;
  16505. default:
  16506. return vis1;
  16507. }
  16508. case MethodFlags.Family:
  16509. switch (vis2){
  16510. case MethodFlags.Public:
  16511. return MethodFlags.Public;
  16512. case MethodFlags.FamORAssem:
  16513. case MethodFlags.Assembly:
  16514. return MethodFlags.FamORAssem;
  16515. default:
  16516. return vis1;
  16517. }
  16518. default:
  16519. return vis2;
  16520. }
  16521. }
  16522. #if !NoReflection
  16523. public virtual object Invoke(object targetObject, params object[] arguments){
  16524. System.Reflection.MethodInfo methInfo = this.GetMethodInfo();
  16525. if (methInfo == null) return null;
  16526. return methInfo.Invoke(targetObject, arguments);
  16527. }
  16528. public virtual Literal Invoke(Literal/*!*/ targetObject, params Literal[] arguments){
  16529. int n = arguments == null ? 0 : arguments.Length;
  16530. object[] args = n == 0 ? null : new object[n];
  16531. if (args != null && arguments != null)
  16532. for (int i = 0; i < n; i++) {
  16533. Literal lit = arguments[i];
  16534. args[i] = lit == null ? null : lit.Value;
  16535. }
  16536. return new Literal(this.Invoke(targetObject.Value, args));
  16537. }
  16538. #endif
  16539. #if !MinimalReader
  16540. protected bool isNormalized;
  16541. public virtual bool IsNormalized{
  16542. get{
  16543. if (this.isNormalized) return true;
  16544. if (this.DeclaringType == null || this.SourceContext.Document != null) return false;
  16545. return this.isNormalized = this.DeclaringType.IsNormalized;
  16546. }
  16547. set{
  16548. this.isNormalized = value;
  16549. }
  16550. }
  16551. #endif
  16552. public virtual bool IsAbstract{
  16553. get{return (this.Flags & MethodFlags.Abstract) != 0;}
  16554. }
  16555. public override bool IsAssembly{
  16556. get{return (this.Flags & MethodFlags.MethodAccessMask) == MethodFlags.Assembly;}
  16557. }
  16558. public override bool IsCompilerControlled{
  16559. get{return (this.Flags & MethodFlags.MethodAccessMask) == MethodFlags.CompilerControlled;}
  16560. }
  16561. public virtual bool IsExtern{
  16562. get{return (this.Flags & MethodFlags.PInvokeImpl) != 0 || (this.ImplFlags & (MethodImplFlags.Runtime|MethodImplFlags.InternalCall)) != 0;}
  16563. }
  16564. public override bool IsFamily{
  16565. get{return (this.Flags & MethodFlags.MethodAccessMask) == MethodFlags.Family;}
  16566. }
  16567. public override bool IsFamilyAndAssembly{
  16568. get{return (this.Flags & MethodFlags.MethodAccessMask) == MethodFlags.FamANDAssem;}
  16569. }
  16570. public override bool IsFamilyOrAssembly{
  16571. get{return (this.Flags & MethodFlags.MethodAccessMask) == MethodFlags.FamORAssem;}
  16572. }
  16573. public virtual bool IsFinal{
  16574. get{return (this.Flags & MethodFlags.Final) != 0;}
  16575. }
  16576. #if !MinimalReader
  16577. public virtual bool IsInternalCall {
  16578. get { return (this.ImplFlags & MethodImplFlags.InternalCall) != 0; }
  16579. }
  16580. #endif
  16581. public override bool IsPrivate {
  16582. get{return (this.Flags & MethodFlags.MethodAccessMask) == MethodFlags.Private;}
  16583. }
  16584. public override bool IsPublic{
  16585. get{return (this.Flags & MethodFlags.MethodAccessMask) == MethodFlags.Public;}
  16586. }
  16587. public override bool IsSpecialName{
  16588. get{return (this.Flags & MethodFlags.SpecialName) != 0;}
  16589. }
  16590. public override bool IsStatic{
  16591. get{return (this.Flags & MethodFlags.Static) != 0;}
  16592. }
  16593. /// <summary>
  16594. /// True if this method can in principle be overridden by a method in a derived class.
  16595. /// </summary>
  16596. public virtual bool IsVirtual{
  16597. get{return (this.Flags & MethodFlags.Virtual) != 0;}
  16598. }
  16599. #if !MinimalReader
  16600. public virtual bool IsNonSealedVirtual{
  16601. get{
  16602. return (this.Flags & MethodFlags.Virtual) != 0 && (this.Flags & MethodFlags.Final) == 0 &&
  16603. (this.DeclaringType == null || (this.DeclaringType.Flags & TypeFlags.Sealed) == 0);
  16604. }
  16605. }
  16606. public virtual bool IsVirtualAndNotDeclaredInStruct{
  16607. get{
  16608. return (this.Flags & MethodFlags.Virtual) != 0 && (this.DeclaringType == null || !(this.DeclaringType is Struct));
  16609. }
  16610. }
  16611. #endif
  16612. public override bool IsVisibleOutsideAssembly{
  16613. get{
  16614. if (this.DeclaringType != null && !this.DeclaringType.IsVisibleOutsideAssembly) return false;
  16615. switch(this.Flags & MethodFlags.MethodAccessMask){
  16616. case MethodFlags.Public:
  16617. return true;
  16618. case MethodFlags.Family:
  16619. case MethodFlags.FamORAssem:
  16620. if (this.DeclaringType != null && !this.DeclaringType.IsSealed) return true;
  16621. goto default;
  16622. default:
  16623. for (int i = 0, n = this.ImplementedInterfaceMethods == null ? 0 : this.ImplementedInterfaceMethods.Count; i < n; i++){
  16624. Method m = this.ImplementedInterfaceMethods[i];
  16625. if (m == null) continue;
  16626. if (m.DeclaringType != null && !m.DeclaringType.IsVisibleOutsideAssembly) continue;
  16627. if (m.IsVisibleOutsideAssembly) return true;
  16628. }
  16629. return false;
  16630. }
  16631. }
  16632. }
  16633. #if ExtendedRuntime
  16634. /// <summary>
  16635. /// VERY IMPORTANT! This property is true only for those pure methods that are *neither*
  16636. /// confined [Reads(Owned)] *nor* state independent [Reads(Nothing)]
  16637. /// </summary>
  16638. public bool IsPure{
  16639. get{
  16640. AttributeNode attr = this.GetAttributeFromSelfOrDeclaringMember(SystemTypes.PureAttribute);
  16641. if (attr == null) return false; // no [Pure] at all
  16642. ExpressionList exprs = attr.Expressions;
  16643. if (exprs != null && 0 < exprs.Count) {
  16644. Literal lit = exprs[0] as Literal;
  16645. if (lit != null && (lit.Value is bool)) {
  16646. bool val = (bool)lit.Value;
  16647. if (!val) return false; // [Pure(false)]
  16648. }
  16649. }
  16650. // pure methods must be marked as [Pure] *and* [Reads(Everything)]
  16651. AttributeNode a = this.GetAttributeFromSelfOrDeclaringMember(SystemTypes.ReadsAttribute);
  16652. if (a == null) return false;
  16653. Literal l = a.GetPositionalArgument(0) as Literal;
  16654. if (l == null) return false; // because default ctor for Reads sets it to "Owned", not "Everything"
  16655. Microsoft.Contracts.ReadsAttribute.Reads r = (Microsoft.Contracts.ReadsAttribute.Reads)l.Value;
  16656. return r == Microsoft.Contracts.ReadsAttribute.Reads.Everything;
  16657. }
  16658. }
  16659. public bool ApplyDefaultContract {
  16660. get{
  16661. return this.GetAttribute(SystemTypes.NoDefaultContractAttribute) == null;
  16662. }
  16663. }
  16664. public bool IsPropertyGetter{
  16665. get{
  16666. if (this.DeclaringMember == null) return false;
  16667. Property p = this.DeclaringMember as Property;
  16668. if (p == null) return false;
  16669. if (p.Getter == this) return true;
  16670. if (this.Template != null) {
  16671. p = this.Template.DeclaringMember as Property;
  16672. if (p != null) return p.Getter == this.Template;
  16673. }
  16674. return false;
  16675. }
  16676. }
  16677. public bool IsPropertySetter {
  16678. get {
  16679. if (this.DeclaringMember == null) return false;
  16680. Property p = this.DeclaringMember as Property;
  16681. if (p == null) return false;
  16682. if (p.Setter == this) return true;
  16683. if (this.Template != null) {
  16684. p = this.Template.DeclaringMember as Property;
  16685. if (p != null) return p.Setter == this.Template;
  16686. }
  16687. return false;
  16688. }
  16689. }
  16690. public bool IsConfined {
  16691. get{
  16692. if (this.DeclaringType is Struct || this.IsStatic) return false; // structs can't own anything
  16693. // default: instance property getters are confined
  16694. if (this.ApplyDefaultContract && this.IsPropertyGetter &&
  16695. this.GetAttributeFromSelfOrDeclaringMember(SystemTypes.PureAttribute) == null) {
  16696. return true;
  16697. }
  16698. // TODO: Remove the next if test after LKG > 11215 (20 December 2007)
  16699. if (this.GetAttributeFromSelfOrDeclaringMember(SystemTypes.ConfinedAttribute) != null) return true;
  16700. AttributeNode attr = this.GetAttributeFromSelfOrDeclaringMember(SystemTypes.PureAttribute);
  16701. if (attr == null)
  16702. return false; // not pure at all, so how could it be confined?
  16703. // Make sure it isn't [Pure(false)]
  16704. ExpressionList exprs = attr.Expressions;
  16705. if (exprs != null && 0 < exprs.Count) {
  16706. Literal lit = exprs[0] as Literal;
  16707. if (lit != null && (lit.Value is bool)) {
  16708. bool val = (bool)lit.Value;
  16709. if (!val) return false; // [Pure(false)]
  16710. }
  16711. }
  16712. AttributeNode a = this.GetAttributeFromSelfOrDeclaringMember(SystemTypes.ReadsAttribute);
  16713. if (a == null) {
  16714. // [Pure] by itself means confined on an instance method in a class
  16715. // otherwise, must specify Reads(Owned) in order to be considered confined
  16716. return !this.IsStatic;
  16717. }
  16718. Literal l = a.GetPositionalArgument(0) as Literal;
  16719. if (l == null) return true; // because default ctor for Reads sets it that way
  16720. Microsoft.Contracts.ReadsAttribute.Reads r = (Microsoft.Contracts.ReadsAttribute.Reads)l.Value;
  16721. return r == Microsoft.Contracts.ReadsAttribute.Reads.Owned;
  16722. }
  16723. }
  16724. public bool IsWriteConfined {
  16725. get {
  16726. return this.GetAttributeFromSelfOrDeclaringMember(SystemTypes.WriteConfinedAttribute) != null
  16727. || IsConfined || IsStateIndependent;
  16728. }
  16729. }
  16730. public bool IsStateIndependent{
  16731. get{
  16732. if (this.ApplyDefaultContract && this.IsPropertyGetter && (this.DeclaringType is Struct || this.IsStatic) &&
  16733. this.GetAttributeFromSelfOrDeclaringMember(SystemTypes.PureAttribute) == null) {
  16734. return true;
  16735. }
  16736. // TODO: Remove the next if test after LKG > 11215 (20 December 2007)
  16737. if (this.GetAttributeFromSelfOrDeclaringMember(SystemTypes.StateIndependentAttribute) != null) return true;
  16738. AttributeNode attr = this.GetAttributeFromSelfOrDeclaringMember(SystemTypes.PureAttribute);
  16739. if (attr == null)
  16740. return false; // not pure at all, so how could it be confined?
  16741. // Make sure it isn't [Pure(false)]
  16742. ExpressionList exprs = attr.Expressions;
  16743. if (exprs != null && 0 < exprs.Count) {
  16744. Literal lit = exprs[0] as Literal;
  16745. if (lit != null && (lit.Value is bool)) {
  16746. bool val = (bool)lit.Value;
  16747. if (!val) return false; // [Pure(false)]
  16748. }
  16749. }
  16750. AttributeNode a = this.GetAttributeFromSelfOrDeclaringMember(SystemTypes.ReadsAttribute);
  16751. if (a == null) {
  16752. // [Pure] by itself means state independent on an instance method in a struct
  16753. // or any a static method (either in a struct or in a class)
  16754. // otherwise, must specify Reads(Nothing) in order to be considered state independent
  16755. return this.IsStatic || this.DeclaringType is Struct;
  16756. }
  16757. Literal l = a.GetPositionalArgument(0) as Literal;
  16758. if (l == null) return false; // because default ctor for Reads sets it that way
  16759. Microsoft.Contracts.ReadsAttribute.Reads r = (Microsoft.Contracts.ReadsAttribute.Reads)l.Value;
  16760. return r == Microsoft.Contracts.ReadsAttribute.Reads.Nothing;
  16761. }
  16762. }
  16763. #endif
  16764. #if !MinimalReader
  16765. public bool IsVarArg {
  16766. get { return (this.CallingConvention & CallingConventionFlags.VarArg) != 0; }
  16767. }
  16768. // whether this is a FieldInitializerMethod (declared in Sing#)
  16769. public virtual bool IsFieldInitializerMethod {
  16770. get{
  16771. return false;
  16772. }
  16773. }
  16774. #endif
  16775. public override Member HiddenMember{
  16776. get{
  16777. return this.HiddenMethod;
  16778. }
  16779. set{
  16780. this.HiddenMethod = (Method)value;
  16781. }
  16782. }
  16783. public virtual Method HiddenMethod{
  16784. get{
  16785. if (this.hiddenMember == Method.NotSpecified) return null;
  16786. Method hiddenMethod = this.hiddenMember as Method;
  16787. if (hiddenMethod != null) return hiddenMethod;
  16788. if (this.ProvideBody == null) return null;
  16789. if (this.IsVirtual && (this.Flags & MethodFlags.VtableLayoutMask) != MethodFlags.NewSlot) return null;
  16790. TypeNode baseType = this.DeclaringType.BaseType;
  16791. while (baseType != null){
  16792. MemberList baseMembers = baseType.GetMembersNamed(this.Name);
  16793. if (baseMembers != null)
  16794. for (int i = 0, n = baseMembers.Count; i < n; i++){
  16795. Method bmeth = baseMembers[i] as Method;
  16796. if (bmeth == null) continue;
  16797. if (!bmeth.ParametersMatch(this.Parameters)){
  16798. if (this.TemplateParameters != null && this.TemplateParametersMatch(bmeth.TemplateParameters)){
  16799. if (!bmeth.ParametersMatchStructurally(this.Parameters)) continue;
  16800. }else
  16801. continue;
  16802. }
  16803. hiddenMethod = bmeth;
  16804. goto done;
  16805. }
  16806. baseType = baseType.BaseType;
  16807. }
  16808. done:
  16809. if (hiddenMethod == null){
  16810. this.hiddenMember = Method.NotSpecified;
  16811. return null;
  16812. }
  16813. this.hiddenMember = hiddenMethod;
  16814. return hiddenMethod;
  16815. }
  16816. set{
  16817. this.hiddenMember = value;
  16818. }
  16819. }
  16820. public override Member OverriddenMember{
  16821. get{
  16822. return this.OverriddenMethod;
  16823. }
  16824. set{
  16825. this.OverriddenMethod = (Method)value;
  16826. }
  16827. }
  16828. public virtual Method OverriddenMethod{
  16829. get{
  16830. if ((this.Flags & MethodFlags.VtableLayoutMask) == MethodFlags.NewSlot) return null;
  16831. if (this.overriddenMember == Method.NotSpecified) return null;
  16832. Method overriddenMethod = this.overriddenMember as Method;
  16833. if (overriddenMethod != null) return overriddenMethod;
  16834. if (this.ProvideBody == null) return null;
  16835. if (!this.IsVirtual) return null;
  16836. TypeNode baseType = this.DeclaringType.BaseType;
  16837. while (baseType != null){
  16838. MemberList baseMembers = baseType.GetMembersNamed(this.Name);
  16839. if (baseMembers != null)
  16840. for (int i = 0, n = baseMembers.Count; i < n; i++){
  16841. Method bmeth = baseMembers[i] as Method;
  16842. if (bmeth == null) continue;
  16843. if (!bmeth.ParametersMatch(this.Parameters)){
  16844. if (this.TemplateParameters != null && this.TemplateParametersMatch(bmeth.TemplateParameters)){
  16845. if (!bmeth.ParametersMatchStructurally(this.Parameters)) continue;
  16846. }else
  16847. continue;
  16848. }
  16849. overriddenMethod = bmeth;
  16850. goto done;
  16851. }
  16852. baseType = baseType.BaseType;
  16853. }
  16854. done:
  16855. if (overriddenMethod == null){
  16856. this.overriddenMember = Method.NotSpecified;
  16857. return null;
  16858. }
  16859. this.overriddenMember = overriddenMethod;
  16860. return overriddenMethod;
  16861. }
  16862. set{
  16863. this.overriddenMember = value;
  16864. }
  16865. }
  16866. #if !NoReflection
  16867. public static Method GetMethod(System.Reflection.MethodInfo methodInfo){
  16868. if (methodInfo == null) return null;
  16869. #if WHIDBEY
  16870. if (methodInfo.IsGenericMethod && !methodInfo.IsGenericMethodDefinition){
  16871. try{
  16872. Method template = Method.GetMethod(methodInfo.GetGenericMethodDefinition());
  16873. if (template == null) return null;
  16874. TypeNodeList templateArguments = new TypeNodeList();
  16875. foreach (Type arg in methodInfo.GetGenericArguments())
  16876. templateArguments.Add(TypeNode.GetTypeNode(arg));
  16877. return template.GetTemplateInstance(template.DeclaringType, templateArguments);
  16878. }catch{
  16879. //TODO: log error
  16880. return null;
  16881. }
  16882. }
  16883. #endif
  16884. TypeNode tn = TypeNode.GetTypeNode(methodInfo.DeclaringType);
  16885. if (tn == null) return null;
  16886. System.Reflection.ParameterInfo[] paramInfos = methodInfo.GetParameters();
  16887. int n = paramInfos == null ? 0 : paramInfos.Length;
  16888. TypeNode[] parameterTypes = new TypeNode[n];
  16889. for (int i = 0; i < n; i++){
  16890. System.Reflection.ParameterInfo param = paramInfos[i];
  16891. if (param == null) return null;
  16892. parameterTypes[i] = TypeNode.GetTypeNode(param.ParameterType);
  16893. }
  16894. TypeNodeList paramTypes = new TypeNodeList(parameterTypes);
  16895. TypeNode returnType = TypeNode.GetTypeNode(methodInfo.ReturnType);
  16896. MemberList members = tn.GetMembersNamed(Identifier.For(methodInfo.Name));
  16897. for (int i = 0, m = members == null ? 0 : members.Count; i < m; i++){
  16898. Method meth = members[i] as Method;
  16899. if (meth == null) continue;
  16900. if (!meth.ParameterTypesMatch(paramTypes)) continue;
  16901. if (meth.ReturnType != returnType) continue;
  16902. return meth;
  16903. }
  16904. return null;
  16905. }
  16906. #endif
  16907. #if !NoReflection && !MinimalReader && WHIDBEY
  16908. protected System.Reflection.Emit.DynamicMethod dynamicMethod;
  16909. public virtual System.Reflection.Emit.DynamicMethod GetDynamicMethod(){
  16910. return this.GetDynamicMethod(false);
  16911. }
  16912. public virtual System.Reflection.Emit.DynamicMethod GetDynamicMethod(bool skipVisibility)
  16913. //^ requires this.DeclaringType != null && this.DeclaringType.DeclaringModule != null && this.IsNormalized && this.Name != null && this.ReturnType != null;
  16914. //^ requires (this.CallingConvention & CallingConventionFlags.ArgumentConvention) == CallingConventionFlags.StandardCall;
  16915. //^ requires !this.IsGeneric;
  16916. {
  16917. if (this.dynamicMethod == null){
  16918. if (this.DeclaringType == null || this.DeclaringType.DeclaringModule == null || !this.IsNormalized || this.Name == null || this.ReturnType == null){
  16919. Debug.Assert(false); return null;
  16920. }
  16921. if ((this.CallingConvention & CallingConventionFlags.ArgumentConvention) != CallingConventionFlags.StandardCall || this.IsGeneric){
  16922. Debug.Assert(false); return null;
  16923. }
  16924. string name = this.Name.Name;
  16925. System.Reflection.MethodAttributes attrs = (System.Reflection.MethodAttributes)this.Flags;
  16926. System.Reflection.CallingConventions callConv = System.Reflection.CallingConventions.Standard;
  16927. callConv |= (System.Reflection.CallingConventions)(this.CallingConvention & ~CallingConventionFlags.ArgumentConvention);
  16928. System.Type rtype = this.ReturnType.GetRuntimeType();
  16929. System.Type owner = this.DeclaringType.GetRuntimeType();
  16930. if (owner == null) { Debug.Fail(""); return null; }
  16931. System.Reflection.Module module = owner.Module;
  16932. System.Reflection.Emit.DynamicMethod dmeth;
  16933. int numPars = this.Parameters == null ? 0 : this.Parameters.Count;
  16934. System.Type[] paramTypes = new Type[numPars];
  16935. for (int i = 0; i < numPars; i++){
  16936. Parameter par = this.Parameters[i];
  16937. if (par == null || par.Type == null){Debug.Assert(false); return null;}
  16938. paramTypes[i] = par.Type.GetRuntimeType();
  16939. }
  16940. if (this.DeclaringType == this.DeclaringType.DeclaringModule.Types[0])
  16941. dmeth = new System.Reflection.Emit.DynamicMethod(name, attrs, callConv, rtype, paramTypes, module, skipVisibility);
  16942. else
  16943. dmeth = new System.Reflection.Emit.DynamicMethod(name, attrs, callConv, rtype, paramTypes, owner, skipVisibility);
  16944. dmeth.InitLocals = true;
  16945. ReGenerator reGenerator = new ReGenerator(dmeth.GetILGenerator());
  16946. reGenerator.VisitMethod(this);
  16947. }
  16948. return this.dynamicMethod;
  16949. }
  16950. #endif
  16951. #if !NoReflection
  16952. protected System.Reflection.MethodInfo methodInfo;
  16953. public virtual System.Reflection.MethodInfo GetMethodInfo(){
  16954. if (this.methodInfo == null){
  16955. if (this.DeclaringType == null) return null;
  16956. #if WHIDBEY
  16957. if (this.IsGeneric && this.Template != null){
  16958. try{
  16959. System.Reflection.MethodInfo templateInfo = this.Template.GetMethodInfo();
  16960. if (templateInfo == null) return null;
  16961. TypeNodeList args = this.TemplateArguments;
  16962. Type[] arguments = new Type[args.Count];
  16963. for (int i = 0; i < args.Count; i++) arguments[i] = args[i].GetRuntimeType();
  16964. return templateInfo.MakeGenericMethod(arguments);
  16965. }catch{
  16966. //TODO: log error
  16967. return null;
  16968. }
  16969. }
  16970. #endif
  16971. Type t = this.DeclaringType.GetRuntimeType();
  16972. if (t == null) return null;
  16973. Type retType = typeof(object);
  16974. if (!this.isGeneric) {
  16975. //Can't do this for generic methods since it may involve a method type parameter
  16976. retType = this.ReturnType.GetRuntimeType();
  16977. if (retType == null) return null;
  16978. }
  16979. ParameterList pars = this.Parameters;
  16980. int n = pars == null ? 0 : pars.Count;
  16981. Type[] types = new Type[n];
  16982. for (int i = 0; i < n; i++){
  16983. Parameter p = pars[i];
  16984. if (p == null || p.Type == null) return null;
  16985. Type pt;
  16986. if (this.isGeneric)
  16987. pt = types[i] = typeof(object); //Have to cheat here since the type might involve a type parameter of the method and getting the runtime type for that is a problem
  16988. //unless we already have the method info in hand
  16989. else
  16990. pt = types[i] = p.Type.GetRuntimeType();
  16991. if (pt == null) return null;
  16992. }
  16993. System.Reflection.MemberInfo[] members = t.GetMember(this.Name.ToString(), System.Reflection.MemberTypes.Method,
  16994. BindingFlags.DeclaredOnly|BindingFlags.Instance|BindingFlags.Static|BindingFlags.Public|BindingFlags.NonPublic);
  16995. foreach (System.Reflection.MethodInfo meth in members){
  16996. if (meth == null) continue;
  16997. if (meth.IsStatic != this.IsStatic) continue;
  16998. if (meth.ReturnType != retType) continue;
  16999. #if WHIDBEY
  17000. if (meth.IsGenericMethodDefinition) {
  17001. TypeNodeList templateParams = this.TemplateParameters;
  17002. Type[] genericArgs = meth.GetGenericArguments();
  17003. if (templateParams == null || genericArgs == null || templateParameters.Count != genericArgs.Length) goto tryNext;
  17004. for (int i = 0, m = genericArgs.Length; i < m; i++) {
  17005. TypeNode t1 = templateParameters[i];
  17006. Type t2 = genericArgs[i];
  17007. if (t1 == null || t2 == null || t1.Name == null || t1.Name.Name != t2.Name) goto tryNext;
  17008. }
  17009. }
  17010. #endif
  17011. System.Reflection.ParameterInfo[] parameters = meth.GetParameters();
  17012. int parCount = parameters == null ? 0 : parameters.Length;
  17013. if (parCount != n) continue;
  17014. for (int i = 0; i < n; i++){
  17015. //^ assert parameters != null;
  17016. System.Reflection.ParameterInfo par = parameters[i];
  17017. if (par == null) goto tryNext;
  17018. if (this.isGeneric) {
  17019. //We don't have the runtime type for the parameter, so just check that the name is the same
  17020. Parameter p = pars[i];
  17021. if (par.Name != p.Name.Name) goto tryNext;
  17022. } else {
  17023. if (par.ParameterType != types[i]) goto tryNext;
  17024. }
  17025. }
  17026. return this.methodInfo = meth;
  17027. tryNext:;
  17028. }
  17029. }
  17030. return this.methodInfo;
  17031. }
  17032. #endif
  17033. #if !MinimalReader
  17034. protected TypeNode[] parameterTypes;
  17035. public virtual TypeNode[]/*!*/ GetParameterTypes() {
  17036. if (this.parameterTypes != null) return this.parameterTypes;
  17037. ParameterList pars = this.Parameters;
  17038. int n = pars == null ? 0 : pars.Count;
  17039. TypeNode[] types = this.parameterTypes = new TypeNode[n];
  17040. for (int i = 0; i < n; i++){
  17041. Parameter p = pars[i];
  17042. if (p == null) continue;
  17043. types[i] = p.Type;
  17044. }
  17045. return types;
  17046. }
  17047. #endif
  17048. public virtual bool ParametersMatch(ParameterList parameters){
  17049. ParameterList pars = this.Parameters;
  17050. int n = pars == null ? 0 : pars.Count;
  17051. int m = parameters == null ? 0 : parameters.Count;
  17052. if (n != m) return false;
  17053. if (parameters == null) return true;
  17054. for (int i = 0; i < n; i++){
  17055. Parameter par1 = pars[i];
  17056. Parameter par2 = parameters[i];
  17057. if (par1 == null || par2 == null) return false;
  17058. if (par1.Type != par2.Type) return false;
  17059. }
  17060. return true;
  17061. }
  17062. #if !MinimalReader
  17063. public virtual bool ParametersMatchExceptLast(ParameterList parameters){
  17064. ParameterList pars = this.Parameters;
  17065. int n = pars == null ? 0 : pars.Count;
  17066. int m = parameters == null ? 0 : parameters.Count;
  17067. if (n != m) return false;
  17068. if (parameters == null) return true;
  17069. for (int i = 0; i < n-1; i++){
  17070. Parameter par1 = pars[i];
  17071. Parameter par2 = parameters[i];
  17072. if (par1 == null || par2 == null) return false;
  17073. if (par1.Type != par2.Type) return false;
  17074. }
  17075. return true;
  17076. }
  17077. #endif
  17078. public virtual bool ParametersMatchStructurally(ParameterList parameters){
  17079. ParameterList pars = this.Parameters;
  17080. int n = pars == null ? 0 : pars.Count;
  17081. int m = parameters == null ? 0 : parameters.Count;
  17082. if (n != m) return false;
  17083. if (parameters == null) return true;
  17084. for (int i = 0; i < n; i++){
  17085. Parameter par1 = pars[i];
  17086. Parameter par2 = parameters[i];
  17087. if (par1 == null || par2 == null) return false;
  17088. if (par1.Type == null || par2.Type == null) return false;
  17089. if (par1.Type != par2.Type && !par1.Type.IsStructurallyEquivalentTo(par2.Type)) return false;
  17090. }
  17091. return true;
  17092. }
  17093. #if !MinimalReader
  17094. public virtual bool ParametersMatchStructurallyIncludingOutFlag(ParameterList parameters){
  17095. return this.ParametersMatchStructurallyIncludingOutFlag(parameters, false);
  17096. }
  17097. public virtual bool ParametersMatchStructurallyIncludingOutFlag(ParameterList parameters, bool allowCoVariance){
  17098. ParameterList pars = this.Parameters;
  17099. int n = pars == null ? 0 : pars.Count;
  17100. int m = parameters == null ? 0 : parameters.Count;
  17101. if (n != m) return false;
  17102. if (parameters == null) return true;
  17103. for (int i = 0; i < n; i++){
  17104. Parameter par1 = pars[i];
  17105. Parameter par2 = parameters[i];
  17106. if (par1 == null || par2 == null) return false;
  17107. if (par1.Type == null || par2.Type == null) return false;
  17108. if ((par1.Flags&ParameterFlags.Out) != (par2.Flags&ParameterFlags.Out)) return false;
  17109. if (par1.Type != par2.Type && !par1.Type.IsStructurallyEquivalentTo(par2.Type)){
  17110. if (allowCoVariance && !par2.Type.IsValueType) return par2.Type.IsAssignableTo(par1.Type);
  17111. return false;
  17112. }
  17113. }
  17114. return true;
  17115. }
  17116. public virtual bool ParametersMatchStructurallyExceptLast(ParameterList parameters){
  17117. ParameterList pars = this.Parameters;
  17118. int n = pars == null ? 0 : pars.Count;
  17119. int m = parameters == null ? 0 : parameters.Count;
  17120. if (n != m) return false;
  17121. if (parameters == null) return true;
  17122. for (int i = 0; i < n-1; i++){
  17123. Parameter par1 = pars[i];
  17124. Parameter par2 = parameters[i];
  17125. if (par1 == null || par2 == null) return false;
  17126. if (par1.Type == null || par2.Type == null) return false;
  17127. if (par1.Type != par2.Type && !par1.Type.IsStructurallyEquivalentTo(par2.Type)) return false;
  17128. }
  17129. return true;
  17130. }
  17131. public virtual bool ParametersMatchIncludingOutFlag(ParameterList parameters){
  17132. ParameterList pars = this.Parameters;
  17133. int n = pars == null ? 0 : pars.Count;
  17134. int m = parameters == null ? 0 : parameters.Count;
  17135. if (n != m) return false;
  17136. if (parameters == null) return true;
  17137. for (int i = 0; i < n; i++){
  17138. Parameter par1 = pars[i];
  17139. Parameter par2 = parameters[i];
  17140. if (par1.Type != par2.Type) return false;
  17141. if ((par1.Flags&ParameterFlags.Out) != (par2.Flags&ParameterFlags.Out)) return false;
  17142. }
  17143. return true;
  17144. }
  17145. #endif
  17146. public virtual bool ParameterTypesMatch(TypeNodeList argumentTypes){
  17147. int n = this.Parameters == null ? 0 : this.Parameters.Count;
  17148. int m = argumentTypes == null ? 0 : argumentTypes.Count;
  17149. if (n != m) return false;
  17150. if (argumentTypes == null) return true;
  17151. for (int i = 0; i < n; i++){
  17152. Parameter par = this.Parameters[i];
  17153. if (par == null) return false;
  17154. TypeNode argType = argumentTypes[i];
  17155. if (par.Type != argType){
  17156. TypeNode pType = TypeNode.StripModifiers(par.Type);
  17157. argType = TypeNode.StripModifiers(argType);
  17158. if (pType != argType) return false;
  17159. }
  17160. }
  17161. return true;
  17162. }
  17163. public virtual bool ParameterTypesMatchStructurally(TypeNodeList argumentTypes){
  17164. int n = this.Parameters == null ? 0 : this.Parameters.Count;
  17165. int m = argumentTypes == null ? 0 : argumentTypes.Count;
  17166. if (n != m) return false;
  17167. if (argumentTypes == null) return true;
  17168. for (int i = 0; i < n; i++){
  17169. Parameter par = this.Parameters[i];
  17170. TypeNode argType = argumentTypes[i];
  17171. if (par.Type != argType){
  17172. TypeNode pType = TypeNode.StripModifiers(par.Type);
  17173. argType = TypeNode.StripModifiers(argType);
  17174. if (pType == null || !pType.IsStructurallyEquivalentTo(argType)) return false;
  17175. }
  17176. }
  17177. return true;
  17178. }
  17179. public virtual bool TemplateParametersMatch(TypeNodeList templateParameters){
  17180. TypeNodeList locPars = this.TemplateParameters;
  17181. if (locPars == null) return templateParameters == null || templateParameters.Count == 0;
  17182. if (templateParameters == null) return false;
  17183. int n = locPars.Count;
  17184. if (n != templateParameters.Count) return false;
  17185. for (int i = 0; i < n; i++){
  17186. TypeNode tp1 = locPars[i];
  17187. TypeNode tp2 = templateParameters[i];
  17188. if (tp1 == null || tp2 == null) return false;
  17189. if (tp1 != tp2 && !tp1.IsStructurallyEquivalentTo(tp2)) return false;
  17190. }
  17191. return true;
  17192. }
  17193. #if UseSingularityPDB
  17194. internal TrivialHashtable contextForOffset;
  17195. internal void RecordSequencePoints(PdbFunction methodInfo) {
  17196. if (methodInfo == null || this.contextForOffset != null) return;
  17197. this.contextForOffset = new TrivialHashtable();
  17198. for (int i = 0, n = methodInfo.lines == null ? 0 : methodInfo.lines.Length; i < n; i++) {
  17199. PdbLines lines = methodInfo.lines[i];
  17200. PdbDocument doc = new PdbDocument(lines);
  17201. for (int j = 0, m = lines.lines.Length; j < m; j++) {
  17202. PdbLine line = lines.lines[j];
  17203. if (line.line != 0xfeefee)
  17204. this.contextForOffset[(int)line.offset+1] = new SourceContext(doc, j*2, j*2+1 );
  17205. }
  17206. }
  17207. }
  17208. #elif !ROTOR
  17209. internal TrivialHashtable contextForOffset;
  17210. internal void RecordSequencePoints(ISymUnmanagedMethod methodInfo){
  17211. if (methodInfo == null || this.contextForOffset != null) return;
  17212. this.contextForOffset = new TrivialHashtable();
  17213. uint count = methodInfo.GetSequencePointCount();
  17214. IntPtr[] docPtrs = new IntPtr[count];
  17215. uint[] startLines = new uint[count];
  17216. uint[] startCols = new uint[count];
  17217. uint[] endLines = new uint[count];
  17218. uint[] endCols = new uint[count];
  17219. uint[] offsets = new uint[count];
  17220. uint numPoints;
  17221. methodInfo.GetSequencePoints(count, out numPoints, offsets, docPtrs, startLines, startCols, endLines, endCols);
  17222. Debug.Assert(count==numPoints);
  17223. for (int i = 0; i < count; i++){
  17224. //The magic hex constant below works around weird data reported from GetSequencePoints.
  17225. //The constant comes from ILDASM's source code, which performs essentially the same test.
  17226. const uint Magic = 0xFEEFEE;
  17227. if (startLines[i] >= Magic || endLines[i] >= Magic) continue;
  17228. UnmanagedDocument doc = new UnmanagedDocument(docPtrs[i]);
  17229. this.contextForOffset[(int)offsets[i]+1] =
  17230. #if !FxCop
  17231. new SourceContext(doc, doc.GetOffset(startLines[i], startCols[i]), doc.GetOffset(endLines[i], endCols[i]));
  17232. #else
  17233. new SourceContext(doc.Name, startLines[i], endLines[i], startCols[i], endCols[i]);
  17234. #endif
  17235. }
  17236. for (int i = 0; i < count; i++)
  17237. System.Runtime.InteropServices.Marshal.Release(docPtrs[i]);
  17238. }
  17239. #endif
  17240. private static Method NotSpecified = new Method();
  17241. private Method template;
  17242. /// <summary>The (generic) method template from which this method was instantiated. Null if this is not a (generic) method template instance.</summary>
  17243. public Method Template{
  17244. get{
  17245. Method result = this.template;
  17246. #if ExtendedRuntime
  17247. if (result == null){
  17248. AttributeList attributes = this.Attributes;
  17249. lock(this){
  17250. if (this.template != null) return this.template;
  17251. for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++){
  17252. AttributeNode attr = attributes[i];
  17253. if (attr == null) continue;
  17254. MemberBinding mb = attr.Constructor as MemberBinding;
  17255. if (mb == null || mb.BoundMember == null || mb.BoundMember.DeclaringType != SystemTypes.TemplateInstanceAttribute) continue;
  17256. ExpressionList exprs = attr.Expressions;
  17257. if (exprs == null || exprs.Count != 2) continue;
  17258. Literal lit = exprs[0] as Literal;
  17259. if (lit == null) continue;
  17260. TypeNode templ = lit.Value as TypeNode;
  17261. if (templ != null){
  17262. lit = exprs[1] as Literal;
  17263. if (lit == null) continue;
  17264. object[] types = lit.Value as object[];
  17265. if (types == null) continue;
  17266. int m = types == null ? 0 : types.Length;
  17267. TypeNodeList templateArguments = new TypeNodeList(m);
  17268. for (int j = 0; j < m; j++){
  17269. //^ assert types != null;
  17270. TypeNode t = types[j] as TypeNode;
  17271. if (t == null) continue;
  17272. templateArguments.Add(t);
  17273. }
  17274. this.TemplateArguments = templateArguments;
  17275. MemberList members = templ.GetMembersNamed(this.Name);
  17276. if (members != null)
  17277. for (int j = 0, k = members.Count; j < k; j++){
  17278. Method meth = members[j] as Method;
  17279. if (meth == null) continue;
  17280. if (meth.ParametersMatch(this.Parameters)){
  17281. this.template = result = meth; break;
  17282. }
  17283. }
  17284. }
  17285. }
  17286. if (result == null)
  17287. this.template = Method.NotSpecified;
  17288. }
  17289. }else
  17290. #endif
  17291. if (result == Method.NotSpecified)
  17292. return null;
  17293. return result;
  17294. }
  17295. set{
  17296. this.template = value;
  17297. }
  17298. }
  17299. private TypeNodeList templateArguments;
  17300. /// <summary>
  17301. /// The arguments used when this (generic) method template instance was instantiated.
  17302. /// </summary>
  17303. public TypeNodeList TemplateArguments{
  17304. get{return this.templateArguments;}
  17305. set{this.templateArguments = value;}
  17306. }
  17307. internal TypeNodeList templateParameters;
  17308. public virtual TypeNodeList TemplateParameters{
  17309. get{
  17310. TypeNodeList result = this.templateParameters;
  17311. #if ExtendedRuntime
  17312. if (result == null && this.Template == null){
  17313. this.TemplateParameters = result = new TypeNodeList();
  17314. AttributeList attributes = this.Attributes;
  17315. for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++){
  17316. AttributeNode attr = attributes[i];
  17317. if (attr == null) continue;
  17318. MemberBinding mb = attr.Constructor as MemberBinding;
  17319. if (mb == null || mb.BoundMember == null || mb.BoundMember.DeclaringType != SystemTypes.TemplateAttribute) continue;
  17320. ExpressionList exprs = attr.Expressions;
  17321. if (exprs == null || exprs.Count != 1) continue;
  17322. Literal lit = exprs[0] as Literal;
  17323. if (lit == null) continue;
  17324. object[] types = lit.Value as object[];
  17325. if (types == null) continue;
  17326. for (int j = 0, m = types == null ? 0 : types.Length; j < m; j++){
  17327. TypeNode t = types[j] as TypeNode;
  17328. if (t == null) continue;
  17329. if (t.NodeType == NodeType.TypeParameter || t.NodeType == NodeType.ClassParameter)
  17330. result.Add(t);
  17331. }
  17332. attributes[i] = null;
  17333. }
  17334. }
  17335. if (result == null || result.Count == 0) return null;
  17336. #endif
  17337. return result;
  17338. }
  17339. set{
  17340. this.templateParameters = value;
  17341. }
  17342. }
  17343. public virtual Method/*!*/ GetTemplateInstance(TypeNode referringType, params TypeNode[] typeArguments) {
  17344. return this.GetTemplateInstance(referringType, new TypeNodeList(typeArguments));
  17345. }
  17346. public virtual Method/*!*/ GetTemplateInstance(TypeNode referringType, TypeNodeList typeArguments) {
  17347. if (referringType == null || this.DeclaringType == null){Debug.Assert(false); return this;}
  17348. if (this.IsGeneric) referringType = this.DeclaringType;
  17349. if (referringType != this.DeclaringType && referringType.DeclaringModule == this.DeclaringType.DeclaringModule)
  17350. return this.GetTemplateInstance(this.DeclaringType, typeArguments);
  17351. if (referringType.structurallyEquivalentMethod == null)
  17352. referringType.structurallyEquivalentMethod = new TrivialHashtableUsingWeakReferences();
  17353. Module module = referringType.DeclaringModule;
  17354. if (module == null) return this;
  17355. int n = typeArguments == null ? 0 : typeArguments.Count;
  17356. if (n == 0 || typeArguments == null) return this;
  17357. StringBuilder sb = new StringBuilder(this.Name.ToString());
  17358. sb.Append('<');
  17359. for (int i = 0; i < n; i++){
  17360. TypeNode ta = typeArguments[i]; if (ta == null) continue;
  17361. sb.Append(ta.FullName);
  17362. if (i < n-1) sb.Append(',');
  17363. }
  17364. sb.Append('>');
  17365. Identifier mangledName = Identifier.For(sb.ToString());
  17366. lock(this){
  17367. Method m = (Method)referringType.structurallyEquivalentMethod[mangledName.UniqueIdKey];
  17368. int counter = 1;
  17369. while (m != null){
  17370. if (m.template == this && Method.TypeListsAreEquivalent(m.TemplateArguments, typeArguments))
  17371. return m;
  17372. mangledName = Identifier.For(mangledName.ToString()+counter++);
  17373. m = (Method)referringType.structurallyEquivalentMethod[mangledName.UniqueIdKey];
  17374. }
  17375. Duplicator duplicator = new Duplicator(referringType.DeclaringModule, referringType);
  17376. duplicator.RecordOriginalAsTemplate = true;
  17377. duplicator.SkipBodies = true;
  17378. Method result = duplicator.VisitMethod(this);
  17379. //^ assume result != null;
  17380. result.Attributes = this.Attributes; //These do not get specialized, but may need to get normalized
  17381. result.Name = mangledName;
  17382. result.fullName = null;
  17383. result.template = this;
  17384. result.TemplateArguments = typeArguments;
  17385. TypeNodeList templateParameters = result.TemplateParameters;
  17386. result.TemplateParameters = null;
  17387. #if !MinimalReader
  17388. result.IsNormalized = true;
  17389. #endif
  17390. if (!this.IsGeneric){
  17391. ParameterList pars = this.Parameters;
  17392. ParameterList rpars = result.Parameters;
  17393. if (pars != null && rpars != null && rpars.Count >= pars.Count)
  17394. for (int i = 0, count = pars.Count; i < count; i++){
  17395. Parameter p = pars[i];
  17396. Parameter rp = rpars[i];
  17397. if (p == null || rp == null) continue;
  17398. rp.Attributes = p.Attributes; //These do not get specialized, but may need to get normalized
  17399. }
  17400. }
  17401. if (!this.IsGeneric && !(result.IsStatic) && this.DeclaringType != referringType){
  17402. result.Flags &= ~(MethodFlags.Virtual|MethodFlags.NewSlot);
  17403. result.Flags |= MethodFlags.Static;
  17404. result.CallingConvention &= ~CallingConventionFlags.HasThis;
  17405. result.CallingConvention |= CallingConventionFlags.ExplicitThis;
  17406. ParameterList pars = result.Parameters;
  17407. if (pars == null) result.Parameters = pars = new ParameterList(1);
  17408. Parameter thisPar = new Parameter(StandardIds.This, this.DeclaringType);
  17409. pars.Add(thisPar);
  17410. for (int i = pars.Count-1; i > 0; i--)
  17411. pars[i] = pars[i-1];
  17412. pars[0] = thisPar;
  17413. }
  17414. referringType.structurallyEquivalentMethod[mangledName.UniqueIdKey] = result;
  17415. Specializer specializer = new Specializer(module, templateParameters, typeArguments);
  17416. specializer.VisitMethod(result);
  17417. if (this.IsGeneric){result.DeclaringType = this.DeclaringType; return result;}
  17418. if (this.IsAbstract) return result;
  17419. referringType.Members.Add(result);
  17420. return result;
  17421. }
  17422. }
  17423. private static bool TypeListsAreEquivalent(TypeNodeList list1, TypeNodeList list2){
  17424. if (list1 == null || list2 == null) return list1 == list2;
  17425. int n = list1.Count;
  17426. if (n != list2.Count) return false;
  17427. for (int i = 0; i < n; i++)
  17428. if (list1[i] != list2[i]) return false;
  17429. return true;
  17430. }
  17431. #if !MinimalReader
  17432. /// <summary>
  17433. /// Returns the local associated with the given field, allocating a new local if necessary.
  17434. /// </summary>
  17435. public virtual Local/*!*/ GetLocalForField(Field/*!*/ f){
  17436. Local loc = (Local)this.Locals[f.UniqueKey];
  17437. if (loc == null){
  17438. this.Locals[f.UniqueKey] = loc = new Local(f.Name, f.Type);
  17439. loc.SourceContext = f.Name.SourceContext;
  17440. }
  17441. return loc;
  17442. }
  17443. #endif
  17444. //TODO: Also need to add a method for allocating locals
  17445. public Method CreateExplicitImplementation(TypeNode implementingType, ParameterList parameters, StatementList body){
  17446. Method m = new Method(implementingType, null, this.Name, parameters, this.ReturnType, new Block(body));
  17447. m.CallingConvention = CallingConventionFlags.HasThis;
  17448. m.Flags = MethodFlags.Public | MethodFlags.HideBySig | MethodFlags.Virtual | MethodFlags.NewSlot | MethodFlags.Final;
  17449. m.ImplementedInterfaceMethods = new MethodList(this);
  17450. //m.ImplementedTypes = new TypeNodeList(this.DeclaringType);
  17451. return m;
  17452. }
  17453. public virtual bool TypeParameterCountsMatch(Method meth2){
  17454. if (meth2 == null) return false;
  17455. int n = this.TemplateParameters == null ? 0 : this.TemplateParameters.Count;
  17456. int m = meth2.TemplateParameters == null ? 0 : meth2.TemplateParameters.Count;
  17457. return n == m;
  17458. }
  17459. public override string ToString() {
  17460. return this.DeclaringType.GetFullUnmangledNameWithTypeParameters() + "." + this.Name;
  17461. }
  17462. #if !MinimalReader
  17463. public bool GetIsCompilerGenerated() {
  17464. InstanceInitializer ii = this as InstanceInitializer;
  17465. return this.HasCompilerGeneratedSignature || (ii != null && ii.IsCompilerGenerated);
  17466. }
  17467. #endif
  17468. #if FxCop
  17469. internal override void GetName(MemberFormat options, StringBuilder name)
  17470. {
  17471. base.GetName(options, name);
  17472. AppendTypeParameters(options, name);
  17473. AppendParametersAndReturnType(options, this.Parameters, '(', ')', this.ReturnType, name);
  17474. }
  17475. private void AppendTypeParameters(MemberFormat options, StringBuilder name)
  17476. {
  17477. if (options.ShowGenericMethodTypeParameterNames == false
  17478. || this.templateParameters == null
  17479. || this.templateParameters.Count == 0)
  17480. return;
  17481. name.Append('<');
  17482. TypeNodeList templateParameters = this.TemplateParameters;
  17483. for (int i = 0; i < templateParameters.Count; i++)
  17484. {
  17485. TypeNode templateParameter = templateParameters[i];
  17486. if (i != 0)
  17487. {
  17488. name.Append(',');
  17489. if (options.InsertSpacesBetweenMethodTypeParameters)
  17490. name.Append(' ');
  17491. }
  17492. name.Append(templateParameter.Name.Name);
  17493. }
  17494. name.Append('>');
  17495. }
  17496. internal static void AppendParametersAndReturnType(MemberFormat options, ParameterCollection parameters, char parametersPrefix, char parametersSuffix, TypeNode returnType, StringBuilder name)
  17497. {
  17498. AppendParameters(options.Parameters, parameters, parametersPrefix, parametersSuffix, name);
  17499. AppendReturnType(options.ReturnType, returnType, name);
  17500. }
  17501. internal static void AppendParameters(ParameterFormat options, ParameterCollection parameters, char prefix, char suffix, StringBuilder name)
  17502. {
  17503. if (parameters == null)
  17504. return;
  17505. if (options.TypeName == TypeNameFormat.None && options.ShowParameterNames == false)
  17506. return;
  17507. name.Append(prefix);
  17508. for (int i = 0; i < parameters.Count; ++i)
  17509. {
  17510. Parameter parameter = parameters[i];
  17511. if (i > 0)
  17512. {
  17513. name.Append(',');
  17514. if (options.InsertSpacesBetweenParameters)
  17515. name.Append(' ');
  17516. }
  17517. if (options.TypeName != TypeNameFormat.None)
  17518. {
  17519. parameter.Type.GetName(options, name);
  17520. if (options.ShowParameterNames) name.Append(' ');
  17521. }
  17522. if (options.ShowParameterNames)
  17523. name.Append(parameter.Name.Name);
  17524. }
  17525. name.Append(suffix);
  17526. }
  17527. internal static void AppendReturnType(TypeFormat options, TypeNode returnType, StringBuilder name)
  17528. {
  17529. if (options.TypeName == TypeNameFormat.None)
  17530. return;
  17531. name.Append(':');
  17532. returnType.GetName(options, name);
  17533. }
  17534. #endif
  17535. }
  17536. #if !MinimalReader
  17537. public class ProxyMethod : Method{
  17538. public Method ProxyFor;
  17539. public ProxyMethod(TypeNode declaringType, AttributeList attributes, Identifier name, ParameterList parameters, TypeNode returnType, Block body)
  17540. : base(declaringType, attributes, name, parameters, returnType, body) { }
  17541. }
  17542. #endif
  17543. public class InstanceInitializer : Method{
  17544. #if !MinimalReader
  17545. /// <summary>
  17546. /// True if this constructor calls a constructor declared in the same class, as opposed to the base class.
  17547. /// </summary>
  17548. public bool IsDeferringConstructor;
  17549. /// <summary>
  17550. /// When the source uses the C# compatibility mode, base calls cannot be put after non-null
  17551. /// field initialization, but must be put before the body. But the user can specify where
  17552. /// the base ctor call should be performed by using "base;" as a marker. During parsing
  17553. /// this flag is set so the right code transformations can be performed at code generation.
  17554. /// </summary>
  17555. public bool ContainsBaseMarkerBecauseOfNonNullFields;
  17556. public Block BaseOrDefferingCallBlock;
  17557. public bool IsCompilerGenerated = false;
  17558. #endif
  17559. public InstanceInitializer()
  17560. : base(){
  17561. this.NodeType = NodeType.InstanceInitializer;
  17562. this.CallingConvention = CallingConventionFlags.HasThis;
  17563. this.Flags = MethodFlags.SpecialName|MethodFlags.RTSpecialName;
  17564. this.Name = StandardIds.Ctor;
  17565. this.ReturnType = CoreSystemTypes.Void;
  17566. }
  17567. public InstanceInitializer(MethodBodyProvider provider, object handle)
  17568. : base(provider, handle){
  17569. this.NodeType = NodeType.InstanceInitializer;
  17570. }
  17571. #if ILOFFSETS
  17572. public InstanceInitializer(MethodBodyProvider provider, object handle, int methodToken)
  17573. : base(provider, handle, methodToken)
  17574. {
  17575. this.NodeType = NodeType.InstanceInitializer;
  17576. }
  17577. #endif
  17578. #if !MinimalReader
  17579. public InstanceInitializer(TypeNode declaringType, AttributeList attributes, ParameterList parameters, Block body)
  17580. : this(declaringType, attributes, parameters, body, CoreSystemTypes.Void){
  17581. }
  17582. public InstanceInitializer(TypeNode declaringType, AttributeList attributes, ParameterList parameters, Block body, TypeNode returnType)
  17583. : base(declaringType, attributes, StandardIds.Ctor, parameters, null, body){
  17584. this.NodeType = NodeType.InstanceInitializer;
  17585. this.CallingConvention = CallingConventionFlags.HasThis;
  17586. this.Flags = MethodFlags.SpecialName|MethodFlags.RTSpecialName;
  17587. this.Name = StandardIds.Ctor;
  17588. this.ReturnType = returnType;
  17589. }
  17590. #endif
  17591. #if !NoReflection
  17592. protected System.Reflection.ConstructorInfo constructorInfo;
  17593. public virtual System.Reflection.ConstructorInfo GetConstructorInfo(){
  17594. if (this.constructorInfo == null){
  17595. if (this.DeclaringType == null) return null;
  17596. Type t = this.DeclaringType.GetRuntimeType();
  17597. if (t == null) return null;
  17598. ParameterList pars = this.Parameters;
  17599. int n = pars == null ? 0 : pars.Count;
  17600. Type[] types = new Type[n];
  17601. for (int i = 0; i < n; i++){
  17602. Parameter p = pars[i];
  17603. if (p == null || p.Type == null) return null;
  17604. Type pt = types[i] = p.Type.GetRuntimeType();
  17605. if (pt == null) return null;
  17606. }
  17607. System.Reflection.MemberInfo[] members = t.GetMember(this.Name.ToString(), System.Reflection.MemberTypes.Constructor,
  17608. BindingFlags.DeclaredOnly|BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
  17609. foreach (System.Reflection.ConstructorInfo cons in members){
  17610. if (cons == null) continue;
  17611. System.Reflection.ParameterInfo[] parameters = cons.GetParameters();
  17612. if (parameters != null) {
  17613. if (parameters.Length != n) continue;
  17614. for (int i = 0; i < n; i++) {
  17615. System.Reflection.ParameterInfo par = parameters[i];
  17616. if (par == null || par.ParameterType != types[i]) goto tryNext;
  17617. }
  17618. }
  17619. return this.constructorInfo = cons;
  17620. tryNext:;
  17621. }
  17622. }
  17623. return this.constructorInfo;
  17624. }
  17625. #endif
  17626. #if !NoReflection
  17627. public override System.Reflection.MethodInfo GetMethodInfo(){
  17628. return null;
  17629. }
  17630. public virtual object Invoke(params object[] arguments){
  17631. System.Reflection.ConstructorInfo constr = this.GetConstructorInfo();
  17632. if (constr == null) return null;
  17633. return constr.Invoke(arguments);
  17634. }
  17635. public virtual Literal Invoke(params Literal[] arguments){
  17636. int n = arguments == null ? 0 : arguments.Length;
  17637. object[] args = n == 0 ? null : new object[n];
  17638. if (args != null && arguments != null)
  17639. for (int i = 0; i < n; i++) {
  17640. Literal lit = arguments[i];
  17641. args[i] = lit == null ? null : lit.Value;
  17642. }
  17643. return new Literal(this.Invoke(args));
  17644. }
  17645. #endif
  17646. //initializers never override a base class initializer
  17647. public override bool OverridesBaseClassMember {
  17648. get { return false; }
  17649. set { }
  17650. }
  17651. public override Member OverriddenMember {
  17652. get { return null; }
  17653. set {}
  17654. }
  17655. public override Method OverriddenMethod {
  17656. get { return null; }
  17657. set {}
  17658. }
  17659. public override string ToString() {
  17660. return this.DeclaringType.GetFullUnmangledNameWithTypeParameters() + "(" + this.Parameters + ")";
  17661. }
  17662. #if !MinimalReader
  17663. public virtual MemberList GetAttributeConstructorNamedParameters() {
  17664. TypeNode type = this.DeclaringType;
  17665. if (type == null || !type.IsAssignableTo(SystemTypes.Attribute) || type.Members == null)
  17666. return null;
  17667. MemberList memList = type.Members;
  17668. int n = memList.Count;
  17669. MemberList ml = new MemberList(memList.Count);
  17670. for (int i = 0; i < n; ++i) {
  17671. Property p = memList[i] as Property;
  17672. if (p != null && p.IsPublic) {
  17673. if (p.Setter != null && p.Getter != null)
  17674. ml.Add(p);
  17675. continue;
  17676. }
  17677. Field f = memList[i] as Field;
  17678. if (f != null && !f.IsInitOnly && f.IsPublic) {
  17679. ml.Add(f);
  17680. }
  17681. }
  17682. return ml;
  17683. }
  17684. #endif
  17685. #if FxCop
  17686. internal override void GetName(MemberFormat options, StringBuilder name)
  17687. {
  17688. GetInitializerName(options, this.DeclaringType, this.Parameters, name, StandardIds.Ctor.Name);
  17689. }
  17690. internal static void GetInitializerName(MemberFormat options, TypeNode declaringType, ParameterCollection parameters, StringBuilder name, string methodName)
  17691. {
  17692. if (options.Type.TypeName != TypeNameFormat.None)
  17693. {
  17694. declaringType.GetName(options, name);
  17695. name.Append('.');
  17696. }
  17697. name.Append(methodName);
  17698. AppendParameters(options.Parameters, parameters, '(', ')', name);
  17699. }
  17700. #endif
  17701. }
  17702. public class StaticInitializer : Method{
  17703. public StaticInitializer()
  17704. : base(){
  17705. this.NodeType = NodeType.StaticInitializer;
  17706. this.Flags = MethodFlags.SpecialName|MethodFlags.RTSpecialName|MethodFlags.Static|MethodFlags.HideBySig|MethodFlags.Private;
  17707. this.Name = StandardIds.CCtor;
  17708. this.ReturnType = CoreSystemTypes.Void;
  17709. }
  17710. #if ILOFFSETS
  17711. public StaticInitializer(MethodBodyProvider provider, object handle, int methodToken)
  17712. : base(provider, handle, methodToken)
  17713. {
  17714. this.NodeType = NodeType.StaticInitializer;
  17715. }
  17716. #endif
  17717. public StaticInitializer(MethodBodyProvider provider, object handle)
  17718. : base(provider, handle){
  17719. this.NodeType = NodeType.StaticInitializer;
  17720. }
  17721. #if !MinimalReader
  17722. public StaticInitializer(TypeNode declaringType, AttributeList attributes, Block body)
  17723. : base(declaringType, attributes, StandardIds.CCtor, null, null, body){
  17724. this.NodeType = NodeType.StaticInitializer;
  17725. this.Flags = MethodFlags.SpecialName|MethodFlags.RTSpecialName|MethodFlags.Static|MethodFlags.HideBySig|MethodFlags.Private;
  17726. this.Name = StandardIds.CCtor;
  17727. this.ReturnType = CoreSystemTypes.Void;
  17728. }
  17729. public StaticInitializer(TypeNode declaringType, AttributeList attributes, Block body, TypeNode voidTypeExpression)
  17730. : base(declaringType, attributes, StandardIds.CCtor, null, null, body) {
  17731. this.NodeType = NodeType.StaticInitializer;
  17732. this.Flags = MethodFlags.SpecialName|MethodFlags.RTSpecialName|MethodFlags.Static|MethodFlags.HideBySig|MethodFlags.Private;
  17733. this.Name = StandardIds.CCtor;
  17734. this.ReturnType = voidTypeExpression;
  17735. }
  17736. #endif
  17737. #if !NoReflection
  17738. protected System.Reflection.ConstructorInfo constructorInfo;
  17739. public virtual System.Reflection.ConstructorInfo GetConstructorInfo(){
  17740. if (this.constructorInfo == null){
  17741. if (this.DeclaringType == null) return null;
  17742. Type t = this.DeclaringType.GetRuntimeType();
  17743. if (t == null) return null;
  17744. ParameterList pars = this.Parameters;
  17745. int n = pars == null ? 0 : pars.Count;
  17746. Type[] types = new Type[n];
  17747. for (int i = 0; i < n; i++){
  17748. Parameter p = pars[i];
  17749. if (p == null || p.Type == null) return null;
  17750. Type pt = types[i] = p.Type.GetRuntimeType();
  17751. if (pt == null) return null;
  17752. }
  17753. System.Reflection.MemberInfo[] members = t.GetMember(this.Name.ToString(), System.Reflection.MemberTypes.Constructor,
  17754. BindingFlags.DeclaredOnly|BindingFlags.Static|BindingFlags.Public|BindingFlags.NonPublic);
  17755. foreach (System.Reflection.ConstructorInfo cons in members){
  17756. if (cons == null) continue;
  17757. System.Reflection.ParameterInfo[] parameters = cons.GetParameters();
  17758. int numPars = parameters == null ? 0 : parameters.Length;
  17759. if (numPars != n) continue;
  17760. if (parameters != null)
  17761. for (int i = 0; i < n; i++){
  17762. System.Reflection.ParameterInfo par = parameters[i];
  17763. if (par == null || par.ParameterType != types[i]) goto tryNext;
  17764. }
  17765. return this.constructorInfo = cons;
  17766. tryNext:;
  17767. }
  17768. }
  17769. return this.constructorInfo;
  17770. }
  17771. public override System.Reflection.MethodInfo GetMethodInfo(){
  17772. return null;
  17773. }
  17774. #endif
  17775. //initializers never override a base class initializer
  17776. public override bool OverridesBaseClassMember {
  17777. get { return false; }
  17778. set { }
  17779. }
  17780. public override Member OverriddenMember {
  17781. get { return null; }
  17782. set {}
  17783. }
  17784. public override Method OverriddenMethod {
  17785. get { return null; }
  17786. set {}
  17787. }
  17788. #if FxCop
  17789. internal override void GetName(MemberFormat options, StringBuilder name)
  17790. {
  17791. InstanceInitializer.GetInitializerName(options, this.DeclaringType, this.Parameters, name, StandardIds.CCtor.Name);
  17792. }
  17793. #endif
  17794. }
  17795. #if !MinimalReader
  17796. public class FieldInitializerBlock : Block{
  17797. public TypeNode Type;
  17798. public bool IsStatic;
  17799. public FieldInitializerBlock()
  17800. : base(){
  17801. this.NodeType = NodeType.FieldInitializerBlock;
  17802. }
  17803. public FieldInitializerBlock(TypeNode type, bool isStatic)
  17804. : base(){
  17805. this.NodeType = NodeType.FieldInitializerBlock;
  17806. this.Type = type;
  17807. this.IsStatic = isStatic;
  17808. }
  17809. }
  17810. #endif
  17811. #if !MinimalReader
  17812. public class ParameterField : Field{
  17813. protected Parameter parameter;
  17814. public ParameterField(){
  17815. }
  17816. public ParameterField(TypeNode declaringType, AttributeList attributes, FieldFlags flags, Identifier name,
  17817. TypeNode Type, Literal defaultValue)
  17818. : base(declaringType, attributes, flags, name, Type, defaultValue){
  17819. }
  17820. public virtual Parameter Parameter{
  17821. get{
  17822. return this.parameter;
  17823. }
  17824. set{
  17825. this.parameter = value;
  17826. }
  17827. }
  17828. }
  17829. #endif
  17830. public class Field : Member{
  17831. #if !MinimalReader
  17832. /// <summary>Provides a value that is assigned to the field upon initialization.</summary>
  17833. public Expression Initializer;
  17834. public TypeNode TypeExpression;
  17835. public bool HasOutOfBandContract;
  17836. public InterfaceList ImplementedInterfaces;
  17837. public InterfaceList ImplementedInterfaceExpressions;
  17838. // if this is the backing field for some event, then ForEvent is that event
  17839. public Event ForEvent;
  17840. public bool IsModelfield = false; //set to true if this field serves as the representation of a modelfield in a class
  17841. #endif
  17842. public Field()
  17843. : base(NodeType.Field){
  17844. }
  17845. public Field(Identifier name)
  17846. : base(NodeType.Field){
  17847. this.Name = name;
  17848. }
  17849. public Field(TypeNode declaringType, AttributeList attributes, FieldFlags flags, Identifier name,
  17850. TypeNode type, Literal defaultValue)
  17851. : base(declaringType, attributes, name, NodeType.Field){
  17852. this.defaultValue = defaultValue;
  17853. this.flags = flags;
  17854. this.type = type;
  17855. }
  17856. private Literal defaultValue;
  17857. /// <summary>The compile-time value to be substituted for references to this field if it is a literal.</summary>
  17858. public Literal DefaultValue{ //TODO: rename this to LiteralValue
  17859. get{return this.defaultValue;}
  17860. set{this.defaultValue = value;}
  17861. }
  17862. private FieldFlags flags;
  17863. public FieldFlags Flags{
  17864. get{return this.flags;}
  17865. set{this.flags = value;}
  17866. }
  17867. private int offset;
  17868. public int Offset{
  17869. get{return this.offset;}
  17870. set{this.offset = value;}
  17871. }
  17872. private bool isVolatile;
  17873. /// <summary>True if the field may not be cached. Used for sharing data between multiple threads.</summary>
  17874. public bool IsVolatile{
  17875. get{return this.isVolatile;}
  17876. set{this.isVolatile = value;}
  17877. }
  17878. private TypeNode type;
  17879. /// <summary>The type of values that may be stored in the field.</summary>
  17880. public TypeNode Type{
  17881. get{return this.type;}
  17882. set{this.type = value;}
  17883. }
  17884. private MarshallingInformation marshallingInformation;
  17885. public MarshallingInformation MarshallingInformation{
  17886. get{return this.marshallingInformation;}
  17887. set{this.marshallingInformation = value;}
  17888. }
  17889. private byte[] initialData;
  17890. public byte[] InitialData{
  17891. get{return this.initialData;}
  17892. set{this.initialData = value;}
  17893. }
  17894. internal PESection section;
  17895. public PESection Section{
  17896. get{return this.section;}
  17897. set{this.section = value;}
  17898. }
  17899. protected string fullName;
  17900. public override string/*!*/ FullName {
  17901. get{
  17902. string result = this.fullName;
  17903. if (result == null)
  17904. this.fullName = result = this.DeclaringType.FullName+"."+(this.Name == null ? "" : this.Name.ToString());
  17905. return result;
  17906. }
  17907. }
  17908. #if !NoXml
  17909. protected override Identifier GetDocumentationId(){
  17910. StringBuilder sb = new StringBuilder();
  17911. sb.Append("F:");
  17912. if (this.DeclaringType == null) return Identifier.Empty;
  17913. sb.Append(this.DeclaringType.FullName);
  17914. sb.Append(".");
  17915. if (this.Name == null) return Identifier.Empty;
  17916. sb.Append(this.Name.Name);
  17917. return Identifier.For(sb.ToString());
  17918. }
  17919. #endif
  17920. #if !NoReflection
  17921. public static Field GetField(System.Reflection.FieldInfo fieldInfo){
  17922. if (fieldInfo == null) return null;
  17923. TypeNode tn = TypeNode.GetTypeNode(fieldInfo.DeclaringType);
  17924. if (tn == null) return null;
  17925. return tn.GetField(Identifier.For(fieldInfo.Name));
  17926. }
  17927. #endif
  17928. #if !NoReflection
  17929. protected System.Reflection.FieldInfo fieldInfo;
  17930. public virtual System.Reflection.FieldInfo GetFieldInfo(){
  17931. if (this.fieldInfo == null){
  17932. TypeNode tn = this.DeclaringType;
  17933. if (tn == null) return null;
  17934. Type t = tn.GetRuntimeType();
  17935. if (t == null) return null;
  17936. System.Reflection.BindingFlags flags = System.Reflection.BindingFlags.DeclaredOnly;
  17937. if (this.IsPublic) flags |= System.Reflection.BindingFlags.Public; else flags |= System.Reflection.BindingFlags.NonPublic;
  17938. if (this.IsStatic) flags |= System.Reflection.BindingFlags.Static; else flags |= System.Reflection.BindingFlags.Instance;
  17939. this.fieldInfo = t.GetField(this.Name.ToString(), flags);
  17940. }
  17941. return this.fieldInfo;
  17942. }
  17943. #endif
  17944. /// <summary>True if all references to the field are replaced with a value that is determined at compile-time.</summary>
  17945. public virtual bool IsLiteral{
  17946. get{return (this.Flags & FieldFlags.Literal) != 0;}
  17947. }
  17948. public override bool IsAssembly{
  17949. get{return (this.Flags & FieldFlags.FieldAccessMask) == FieldFlags.Assembly;}
  17950. }
  17951. public override bool IsCompilerControlled{
  17952. get{return (this.Flags & FieldFlags.FieldAccessMask) == FieldFlags.CompilerControlled;}
  17953. }
  17954. public override bool IsFamily{
  17955. get{return (this.Flags & FieldFlags.FieldAccessMask) == FieldFlags.Family;}
  17956. }
  17957. public override bool IsFamilyAndAssembly{
  17958. get{return (this.Flags & FieldFlags.FieldAccessMask) == FieldFlags.FamANDAssem;}
  17959. }
  17960. public override bool IsFamilyOrAssembly{
  17961. get{return (this.Flags & FieldFlags.FieldAccessMask) == FieldFlags.FamORAssem;}
  17962. }
  17963. /// <summary>True if the field may only be assigned to inside the constructor.</summary>
  17964. public virtual bool IsInitOnly{
  17965. get{return (this.Flags & FieldFlags.InitOnly) != 0;}
  17966. }
  17967. public override bool IsPrivate{
  17968. get{return (this.Flags & FieldFlags.FieldAccessMask) == FieldFlags.Private;}
  17969. }
  17970. public override bool IsPublic{
  17971. get{return (this.Flags & FieldFlags.FieldAccessMask) == FieldFlags.Public;}
  17972. }
  17973. public override bool IsSpecialName{
  17974. get{return (this.Flags & FieldFlags.SpecialName) != 0;}
  17975. }
  17976. public override bool IsStatic{
  17977. get{return (this.Flags & FieldFlags.Static) != 0;}
  17978. }
  17979. public override bool IsVisibleOutsideAssembly{
  17980. get{
  17981. if (this.DeclaringType != null && !this.DeclaringType.IsVisibleOutsideAssembly) return false;
  17982. switch(this.Flags & FieldFlags.FieldAccessMask){
  17983. case FieldFlags.Public:
  17984. return true;
  17985. case FieldFlags.Family:
  17986. case FieldFlags.FamORAssem:
  17987. return this.DeclaringType != null && !this.DeclaringType.IsSealed;
  17988. default:
  17989. return false;
  17990. }
  17991. }
  17992. }
  17993. #if !NoReflection
  17994. public virtual object GetValue(object targetObject){
  17995. System.Reflection.FieldInfo fieldInfo = this.GetFieldInfo();
  17996. if (fieldInfo == null) return null;
  17997. return fieldInfo.GetValue(targetObject);
  17998. }
  17999. public virtual Literal GetValue(Literal/*!*/ targetObject){
  18000. return new Literal(this.GetValue(targetObject.Value));
  18001. }
  18002. public virtual void SetValue(object targetObject, object value){
  18003. System.Reflection.FieldInfo fieldInfo = this.GetFieldInfo();
  18004. if (fieldInfo == null) return;
  18005. fieldInfo.SetValue(targetObject, value);
  18006. }
  18007. public virtual void SetValue(Literal/*!*/ targetObject, Literal/*!*/ value) {
  18008. this.SetValue(targetObject.Value, value.Value);
  18009. }
  18010. #endif
  18011. #if ExtendedRuntime
  18012. ReferenceFieldSemantics referenceSemantics;
  18013. public ReferenceFieldSemantics ReferenceSemantics{
  18014. get{
  18015. if (this.referenceSemantics == ReferenceFieldSemantics.NotComputed){
  18016. ReferenceFieldSemantics referenceKind;
  18017. TypeNode t = this.Type;
  18018. if (t == null) return this.referenceSemantics;
  18019. if (t is Struct){
  18020. TypeNodeList args;
  18021. bool b = t.IsAssignableToInstanceOf(SystemTypes.GenericIEnumerable, out args);
  18022. if ( b && args!= null && args.Count > 0 && args[0] != null && args[0].IsObjectReferenceType)
  18023. referenceKind = ReferenceFieldSemantics.EnumerableStructOfReferences;
  18024. else if (t.IsAssignableTo(SystemTypes.IEnumerable))
  18025. referenceKind = ReferenceFieldSemantics.EnumerableStructOfReferences;
  18026. else
  18027. referenceKind = ReferenceFieldSemantics.NonReference;
  18028. }else if (t != null && t.IsObjectReferenceType)
  18029. referenceKind = ReferenceFieldSemantics.Reference;
  18030. else
  18031. referenceKind = ReferenceFieldSemantics.NonReference;
  18032. if (referenceKind == ReferenceFieldSemantics.NonReference)
  18033. this.referenceSemantics = referenceKind | ReferenceFieldSemantics.None;
  18034. else{
  18035. if (this.GetAttribute(SystemTypes.LockProtectedAttribute) != null)
  18036. this.referenceSemantics = referenceKind | ReferenceFieldSemantics.LockProtected;
  18037. else if (this.GetAttribute(SystemTypes.ImmutableAttribute) != null)
  18038. this.referenceSemantics = referenceKind | ReferenceFieldSemantics.Immutable;
  18039. else if (this.GetAttribute(SystemTypes.RepAttribute) != null)
  18040. this.referenceSemantics = referenceKind | ReferenceFieldSemantics.Rep;
  18041. else if (this.GetAttribute(SystemTypes.PeerAttribute) != null)
  18042. this.referenceSemantics = referenceKind | ReferenceFieldSemantics.Peer;
  18043. else {
  18044. ReferenceFieldSemantics r = ReferenceFieldSemantics.None;
  18045. this.referenceSemantics = referenceKind | r;
  18046. }
  18047. }
  18048. }
  18049. return this.referenceSemantics;
  18050. }
  18051. set {
  18052. this.referenceSemantics = value;
  18053. }
  18054. }
  18055. public bool IsOwned{
  18056. get{
  18057. return this.IsRep || this.IsPeer;
  18058. }
  18059. }
  18060. public bool IsOnce
  18061. {
  18062. get {
  18063. return this.GetAttribute(SystemTypes.OnceAttribute) != null;
  18064. }
  18065. }
  18066. public bool IsRep{
  18067. get {
  18068. return this.ReferenceSemantics == (ReferenceFieldSemantics.Rep | ReferenceFieldSemantics.Reference);
  18069. }
  18070. }
  18071. public bool IsPeer {
  18072. get {
  18073. return this.ReferenceSemantics == (ReferenceFieldSemantics.Peer | ReferenceFieldSemantics.Reference);
  18074. }
  18075. }
  18076. public bool IsLockProtected {
  18077. get{
  18078. return this.ReferenceSemantics == (ReferenceFieldSemantics.LockProtected | ReferenceFieldSemantics.Reference);
  18079. }
  18080. }
  18081. public bool IsStrictReadonly {
  18082. get {
  18083. return this.GetAttribute(ExtendedRuntimeTypes.StrictReadonlyAttribute) != null;
  18084. }
  18085. }
  18086. #endif
  18087. public override string ToString() {
  18088. return this.DeclaringType.GetFullUnmangledNameWithTypeParameters() + "." + this.Name;
  18089. }
  18090. #if FxCop
  18091. internal override void GetName(MemberFormat options, StringBuilder name)
  18092. {
  18093. base.GetName(options, name);
  18094. Method.AppendReturnType(options.ReturnType, this.Type, name);
  18095. }
  18096. #endif
  18097. }
  18098. #if ExtendedRuntime
  18099. /// <summary>
  18100. /// The behavior of a field in the Spec# object invariants/ownership/concurrency methodology.
  18101. /// </summary>
  18102. public enum ReferenceFieldSemantics{
  18103. NotComputed,
  18104. None,
  18105. Rep,
  18106. LockProtected,
  18107. Immutable,
  18108. Peer,
  18109. SemanticsMask = 0xff,
  18110. Reference = 0x100,
  18111. EnumerableStructOfReferences = 0x200,
  18112. NonReference = 0x300,
  18113. ReferenceMask = 0xff00,
  18114. }
  18115. #endif
  18116. #if FxCop
  18117. public class PropertyNode : Member{
  18118. #else
  18119. public class Property : Member{
  18120. #endif
  18121. #if !MinimalReader
  18122. /// <summary>
  18123. /// The list of types (just one in C#) that contain abstract or virtual properties that are explicity implemented or overridden by this property.
  18124. /// </summary>
  18125. public TypeNodeList ImplementedTypes;
  18126. public TypeNodeList ImplementedTypeExpressions;
  18127. public bool IsModelfield = false; //set to true if this property serves as the representation of a modelfield in an interface
  18128. #endif
  18129. #if FxCop
  18130. public PropertyNode()
  18131. #else
  18132. public Property()
  18133. #endif
  18134. : base(NodeType.Property){
  18135. }
  18136. #if !MinimalReader
  18137. public Property(TypeNode declaringType, AttributeList attributes, PropertyFlags flags, Identifier name,
  18138. Method getter, Method setter)
  18139. : base(declaringType, attributes, name, NodeType.Property){
  18140. this.flags = flags;
  18141. this.getter = getter;
  18142. this.setter = setter;
  18143. if (getter != null) getter.DeclaringMember = this;
  18144. if (setter != null) setter.DeclaringMember = this;
  18145. }
  18146. #endif
  18147. private PropertyFlags flags;
  18148. public PropertyFlags Flags{
  18149. get{return this.flags;}
  18150. set{this.flags = value;}
  18151. }
  18152. private Method getter;
  18153. /// <summary>The method that is called to get the value of this property. Corresponds to the get clause in C#.</summary>
  18154. public Method Getter{
  18155. get{return this.getter;}
  18156. set{this.getter = value;}
  18157. }
  18158. private Method setter;
  18159. /// <summary>The method that is called to set the value of this property. Corresponds to the set clause in C#.</summary>
  18160. public Method Setter{
  18161. get{return this.setter;}
  18162. set{this.setter = value;}
  18163. }
  18164. private MethodList otherMethods;
  18165. /// <summary>Other methods associated with the property. No equivalent in C#.</summary>
  18166. public MethodList OtherMethods{
  18167. get{return this.otherMethods;}
  18168. set{this.otherMethods = value;}
  18169. }
  18170. protected string fullName;
  18171. public override string/*!*/ FullName {
  18172. get{
  18173. if (this.fullName != null) return this.fullName;
  18174. StringBuilder sb = new StringBuilder();
  18175. sb.Append(this.DeclaringType.FullName);
  18176. sb.Append('.');
  18177. if (this.Name != null)
  18178. sb.Append(this.Name.ToString());
  18179. ParameterList parameters = this.Parameters;
  18180. for (int i = 0, n = parameters == null ? 0 : parameters.Count; i < n; i++){
  18181. Parameter par = parameters[i];
  18182. if (par == null || par.Type == null) continue;
  18183. if (i == 0)
  18184. sb.Append('(');
  18185. else
  18186. sb.Append(',');
  18187. sb.Append(par.Type.FullName);
  18188. if (i == n-1)
  18189. sb.Append(')');
  18190. }
  18191. return this.fullName = sb.ToString();
  18192. }
  18193. }
  18194. #if !MinimalReader
  18195. public virtual Method GetBaseGetter() {
  18196. if (this.HidesBaseClassMember) return null;
  18197. TypeNode t = this.DeclaringType;
  18198. if (t == null) return null;
  18199. while (t.BaseType != null){
  18200. t = t.BaseType;
  18201. MemberList mems = t.GetMembersNamed(this.Name);
  18202. for (int i = 0, n = mems == null ? 0 : mems.Count; i < n; i++) {
  18203. Property bprop = mems[i] as Property;
  18204. if (bprop == null) continue;
  18205. if (!bprop.ParametersMatch(this.Parameters)) continue;
  18206. if (bprop.Getter != null) return bprop.Getter;
  18207. }
  18208. }
  18209. return null;
  18210. }
  18211. public virtual Method GetBaseSetter(){
  18212. if (this.HidesBaseClassMember) return null;
  18213. TypeNode t = this.DeclaringType;
  18214. if (t == null) return null;
  18215. while (t.BaseType != null) {
  18216. t = t.BaseType;
  18217. MemberList mems = t.GetMembersNamed(this.Name);
  18218. for (int i = 0, n = mems == null ? 0 : mems.Count; i < n; i++) {
  18219. Property bprop = mems[i] as Property;
  18220. if (bprop == null) continue;
  18221. if (!bprop.ParametersMatch(this.Parameters)) continue;
  18222. if (bprop.Setter != null) return bprop.Setter;
  18223. }
  18224. }
  18225. return null;
  18226. }
  18227. #endif
  18228. #if !NoXml
  18229. protected override Identifier GetDocumentationId(){
  18230. StringBuilder sb = new StringBuilder(this.DeclaringType.DocumentationId.ToString());
  18231. sb[0] = 'P';
  18232. sb.Append('.');
  18233. if (this.Name != null)
  18234. sb.Append(this.Name.ToString());
  18235. ParameterList parameters = this.Parameters;
  18236. for (int i = 0, n = parameters == null ? 0 : parameters.Count; i < n; i++){
  18237. Parameter par = parameters[i];
  18238. if (par == null || par.Type == null) continue;
  18239. if (i == 0)
  18240. sb.Append('(');
  18241. else
  18242. sb.Append(',');
  18243. par.Type.AppendDocumentIdMangledName(sb, null, this.DeclaringType.TemplateParameters);
  18244. if (i == n-1)
  18245. sb.Append(')');
  18246. }
  18247. return Identifier.For(sb.ToString());
  18248. }
  18249. #endif
  18250. #if !NoReflection
  18251. public static Property GetProperty(System.Reflection.PropertyInfo propertyInfo){
  18252. if (propertyInfo == null) return null;
  18253. TypeNode tn = TypeNode.GetTypeNode(propertyInfo.DeclaringType);
  18254. if (tn == null) return null;
  18255. System.Reflection.ParameterInfo[] paramInfos = propertyInfo.GetIndexParameters();
  18256. int n = paramInfos == null ? 0 : paramInfos.Length;
  18257. TypeNode[] parameterTypes = new TypeNode[n];
  18258. if (paramInfos != null)
  18259. for (int i = 0; i < n; i++){
  18260. System.Reflection.ParameterInfo param = paramInfos[i];
  18261. if (param == null) return null;
  18262. parameterTypes[i] = TypeNode.GetTypeNode(param.ParameterType);
  18263. }
  18264. return tn.GetProperty(Identifier.For(propertyInfo.Name), parameterTypes);
  18265. }
  18266. #endif
  18267. #if !NoReflection
  18268. protected System.Reflection.PropertyInfo propertyInfo;
  18269. public virtual System.Reflection.PropertyInfo GetPropertyInfo(){
  18270. if (this.propertyInfo == null){
  18271. if (this.DeclaringType == null) return null;
  18272. Type t = this.DeclaringType.GetRuntimeType();
  18273. if (t == null) return null;
  18274. if (this.Type == null) return null;
  18275. Type retType = this.Type.GetRuntimeType();
  18276. if (retType == null) return null;
  18277. ParameterList pars = this.Parameters;
  18278. int n = pars == null ? 0 : pars.Count;
  18279. Type[] types = new Type[n];
  18280. for (int i = 0; i < n; i++){
  18281. Parameter p = pars[i];
  18282. if (p == null || p.Type == null) return null;
  18283. Type pt = types[i] = p.Type.GetRuntimeType();
  18284. if (pt == null) return null;
  18285. }
  18286. System.Reflection.MemberInfo[] members =
  18287. t.GetMember(this.Name.ToString(), System.Reflection.MemberTypes.Property,
  18288. BindingFlags.DeclaredOnly|BindingFlags.Instance|BindingFlags.Static|BindingFlags.Public|BindingFlags.NonPublic);
  18289. foreach (System.Reflection.PropertyInfo prop in members){
  18290. if (prop == null || prop.PropertyType != retType) continue;
  18291. System.Reflection.ParameterInfo[] parameters = prop.GetIndexParameters();
  18292. if (parameters == null || parameters.Length != n) continue;
  18293. for (int i = 0; i < n; i++){
  18294. System.Reflection.ParameterInfo parInfo = parameters[i];
  18295. if (parInfo == null || parInfo.ParameterType != types[i]) goto tryNext;
  18296. }
  18297. return this.propertyInfo = prop;
  18298. tryNext:;
  18299. }
  18300. }
  18301. return this.propertyInfo;
  18302. }
  18303. public virtual object GetValue(object targetObject, params object[] indices) {
  18304. System.Reflection.PropertyInfo propInfo = this.GetPropertyInfo();
  18305. if (propInfo == null) throw new InvalidOperationException();
  18306. return propInfo.GetValue(targetObject, indices);
  18307. }
  18308. public virtual Literal GetValue(Literal/*!*/ targetObject, params Literal[] indices){
  18309. int n = indices == null ? 0 : indices.Length;
  18310. object[] inds = n == 0 ? null : new object[n];
  18311. if (inds != null && indices != null)
  18312. for (int i = 0; i < n; i++) {
  18313. Literal lit = indices[i];
  18314. inds[i] = lit == null ? null : lit.Value;
  18315. }
  18316. return new Literal(this.GetValue(targetObject.Value, inds));
  18317. }
  18318. public virtual void SetValue(object targetObject, object value, params object[] indices){
  18319. System.Reflection.PropertyInfo propInfo = this.GetPropertyInfo();
  18320. if (propInfo == null) throw new InvalidOperationException();
  18321. propInfo.SetValue(targetObject, value, indices);
  18322. }
  18323. public virtual void SetValue(Literal/*!*/ targetObject, Literal/*!*/ value, params Literal[] indices){
  18324. int n = indices == null ? 0 : indices.Length;
  18325. object[] inds = n == 0 ? null : new object[n];
  18326. if (inds != null && indices != null)
  18327. for (int i = 0; i < n; i++) {
  18328. Literal lit = indices[i];
  18329. inds[i] = lit == null ? null : lit.Value;
  18330. }
  18331. System.Reflection.PropertyInfo propInfo = this.GetPropertyInfo();
  18332. if (propInfo == null) throw new InvalidOperationException();
  18333. propInfo.SetValue(targetObject.Value, value.Value, inds);
  18334. }
  18335. #endif
  18336. #if !NoXml
  18337. public override string HelpText {
  18338. get {
  18339. if (this.helpText != null)
  18340. return this.helpText;
  18341. StringBuilder sb = new StringBuilder(base.HelpText);
  18342. // if there is already some help text, start the contract on a new line
  18343. bool startWithNewLine = (sb.Length != 0);
  18344. if (this.Getter != null && this.Getter.HelpText != null && this.Getter.HelpText.Length > 0){
  18345. if (startWithNewLine){
  18346. sb.Append("\n");
  18347. startWithNewLine = false;
  18348. }
  18349. sb.Append("get\n");
  18350. int i = sb.Length;
  18351. sb.Append(this.Getter.HelpText);
  18352. if (sb.Length > i)
  18353. startWithNewLine = true;
  18354. }
  18355. if (this.Setter != null && this.Setter.HelpText != null && this.Setter.HelpText.Length > 0) {
  18356. if (startWithNewLine){
  18357. sb.Append("\n");
  18358. startWithNewLine = false;
  18359. }
  18360. sb.Append("set\n");
  18361. sb.Append(this.Setter.HelpText);
  18362. }
  18363. return this.helpText = sb.ToString();
  18364. }
  18365. set {
  18366. base.HelpText = value;
  18367. }
  18368. }
  18369. #endif
  18370. public override bool IsAssembly{
  18371. get{return Method.GetVisibilityUnion(this.Getter, this.Setter) == MethodFlags.Assembly;}
  18372. }
  18373. public override bool IsCompilerControlled{
  18374. get{return Method.GetVisibilityUnion(this.Getter, this.Setter) == MethodFlags.CompilerControlled;}
  18375. }
  18376. public override bool IsFamily{
  18377. get{return Method.GetVisibilityUnion(this.Getter, this.Setter) == MethodFlags.Family;}
  18378. }
  18379. public override bool IsFamilyAndAssembly{
  18380. get{return Method.GetVisibilityUnion(this.Getter, this.Setter) == MethodFlags.FamANDAssem;}
  18381. }
  18382. public override bool IsFamilyOrAssembly{
  18383. get{return Method.GetVisibilityUnion(this.Getter, this.Setter) == MethodFlags.FamORAssem;}
  18384. }
  18385. public bool IsFinal {
  18386. get {return (this.Getter == null || this.Getter.IsFinal) && (this.Setter == null || this.Setter.IsFinal);}
  18387. }
  18388. public override bool IsPrivate {
  18389. get{return Method.GetVisibilityUnion(this.Getter, this.Setter) == MethodFlags.Private;}
  18390. }
  18391. public override bool IsPublic{
  18392. get{return Method.GetVisibilityUnion(this.Getter, this.Setter) == MethodFlags.Public;}
  18393. }
  18394. public override bool IsSpecialName{
  18395. get{return (this.Flags & PropertyFlags.SpecialName) != 0;}
  18396. }
  18397. public override bool IsStatic{
  18398. get{return (this.Getter == null || this.Getter.IsStatic) && (this.Setter == null || this.Setter.IsStatic);}
  18399. }
  18400. /// <summary>
  18401. /// True if this property can in principle be overridden by a property in a derived class.
  18402. /// </summary>
  18403. public bool IsVirtual{
  18404. get{return (this.Getter == null || this.Getter.IsVirtual) && (this.Setter == null || this.Setter.IsVirtual);}
  18405. }
  18406. public override bool IsVisibleOutsideAssembly{
  18407. get{return (this.Getter != null && this.Getter.IsVisibleOutsideAssembly) || (this.Setter != null && this.Setter.IsVisibleOutsideAssembly);}
  18408. }
  18409. public static readonly Property NotSpecified = new Property();
  18410. public override Member HiddenMember{
  18411. get{
  18412. return this.HiddenProperty;
  18413. }
  18414. set{
  18415. this.HiddenProperty = (Property)value;
  18416. }
  18417. }
  18418. protected Property hiddenProperty;
  18419. public virtual Property HiddenProperty{
  18420. get{
  18421. if (this.hiddenMember == Property.NotSpecified) return null;
  18422. Property hiddenProperty = this.hiddenMember as Property;
  18423. if (hiddenProperty != null) return hiddenProperty;
  18424. Method hiddenGetter = this.Getter == null ? null : this.Getter.HiddenMethod;
  18425. Method hiddenSetter = this.Setter == null ? null : this.Setter.HiddenMethod;
  18426. Property hiddenGetterProperty = hiddenGetter == null ? null : hiddenGetter.DeclaringMember as Property;
  18427. Property hiddenSetterProperty = hiddenSetter == null ? null : hiddenSetter.DeclaringMember as Property;
  18428. hiddenProperty = hiddenGetterProperty;
  18429. if (hiddenSetterProperty != null){
  18430. if (hiddenProperty == null ||
  18431. (hiddenSetterProperty.DeclaringType != null && hiddenSetterProperty.DeclaringType.IsDerivedFrom(hiddenProperty.DeclaringType)))
  18432. hiddenProperty = hiddenSetterProperty;
  18433. }
  18434. this.hiddenMember = hiddenProperty;
  18435. return hiddenProperty;
  18436. }
  18437. set{
  18438. this.hiddenMember = value;
  18439. }
  18440. }
  18441. public override Member OverriddenMember{
  18442. get{
  18443. return this.OverriddenProperty;
  18444. }
  18445. set{
  18446. this.OverriddenProperty = (Property)value;
  18447. }
  18448. }
  18449. protected Property overriddenProperty;
  18450. public virtual Property OverriddenProperty{
  18451. get{
  18452. if (this.overriddenMember == Property.NotSpecified) return null;
  18453. Property overriddenProperty = this.overriddenMember as Property;
  18454. if (overriddenProperty != null) return overriddenProperty;
  18455. Method overriddenGetter = this.Getter == null ? null : this.Getter.OverriddenMethod;
  18456. Method overriddenSetter = this.Setter == null ? null : this.Setter.OverriddenMethod;
  18457. Property overriddenGetterProperty = overriddenGetter == null ? null : overriddenGetter.DeclaringMember as Property;
  18458. Property overriddenSetterProperty = overriddenSetter == null ? null : overriddenSetter.DeclaringMember as Property;
  18459. overriddenProperty = overriddenGetterProperty;
  18460. if (overriddenSetterProperty != null){
  18461. if (overriddenProperty == null ||
  18462. (overriddenSetterProperty.DeclaringType != null && overriddenSetterProperty.DeclaringType.IsDerivedFrom(overriddenProperty.DeclaringType)))
  18463. overriddenProperty = overriddenSetterProperty;
  18464. }
  18465. this.overriddenMember = overriddenProperty;
  18466. return overriddenProperty;
  18467. }
  18468. set{
  18469. this.overriddenMember = value;
  18470. }
  18471. }
  18472. private ParameterList parameters;
  18473. /// <summary>
  18474. /// The parameters of this property if it is an indexer.
  18475. /// </summary>
  18476. public ParameterList Parameters{
  18477. get{
  18478. if (this.parameters != null) return this.parameters;
  18479. if (this.Getter != null) return this.parameters = this.Getter.Parameters;
  18480. ParameterList setterPars = this.Setter == null ? null : this.Setter.Parameters;
  18481. int n = setterPars == null ? 0 : setterPars.Count - 1;
  18482. ParameterList propPars = this.parameters = new ParameterList(n);
  18483. if (setterPars != null)
  18484. for (int i = 0; i < n; i++) propPars.Add(setterPars[i]);
  18485. return propPars;
  18486. }
  18487. set{
  18488. this.parameters = value;
  18489. }
  18490. }
  18491. public virtual bool ParametersMatch(ParameterList parameters){
  18492. ParameterList pars = this.Parameters;
  18493. int n = pars == null ? 0 : pars.Count;
  18494. int m = parameters == null ? 0 : parameters.Count;
  18495. if (n != m) return false;
  18496. if (parameters == null) return true;
  18497. for (int i = 0; i < n; i++){
  18498. Parameter par1 = pars[i];
  18499. Parameter par2 = parameters[i];
  18500. if (par1.Type != par2.Type) return false;
  18501. }
  18502. return true;
  18503. }
  18504. public virtual bool ParametersMatchStructurally(ParameterList parameters) {
  18505. ParameterList pars = this.Parameters;
  18506. int n = pars == null ? 0 : pars.Count;
  18507. int m = parameters == null ? 0 : parameters.Count;
  18508. if (n != m) return false;
  18509. if (parameters == null) return true;
  18510. for (int i = 0; i < n; i++) {
  18511. Parameter par1 = pars[i];
  18512. Parameter par2 = parameters[i];
  18513. if (par1 == null || par2 == null) return false;
  18514. if (par1.Type == null || par2.Type == null) return false;
  18515. if (par1.Type != par2.Type && !par1.Type.IsStructurallyEquivalentTo(par2.Type)) return false;
  18516. }
  18517. return true;
  18518. }
  18519. public virtual bool ParameterTypesMatch(TypeNodeList argumentTypes) {
  18520. ParameterList pars = this.Parameters;
  18521. int n = pars == null ? 0 : pars.Count;
  18522. int m = argumentTypes == null ? 0 : argumentTypes.Count;
  18523. if (n != m) return false;
  18524. if (argumentTypes == null) return true;
  18525. for (int i = 0; i < n; i++){
  18526. Parameter par = this.Parameters[i];
  18527. if (par == null) return false;
  18528. TypeNode argType = argumentTypes[i];
  18529. if (par.Type != argType) return false;
  18530. }
  18531. return true;
  18532. }
  18533. protected TypeNode type;
  18534. /// <summary>
  18535. /// The type of value that this property holds.
  18536. /// </summary>
  18537. public virtual TypeNode Type{
  18538. get{
  18539. if (this.type != null) return this.type;
  18540. if (this.Getter != null) return this.type = this.Getter.ReturnType;
  18541. if (this.Setter != null && this.Setter.Parameters != null)
  18542. return this.type = this.Setter.Parameters[this.Setter.Parameters.Count-1].Type;
  18543. return CoreSystemTypes.Object;
  18544. }
  18545. set{
  18546. this.type = value;
  18547. }
  18548. }
  18549. #if !MinimalReader
  18550. public TypeNode TypeExpression;
  18551. #endif
  18552. public override string ToString() {
  18553. return this.DeclaringType.GetFullUnmangledNameWithTypeParameters() + "." + this.Name;
  18554. }
  18555. #if FxCop
  18556. internal override void GetName(MemberFormat options, StringBuilder name)
  18557. {
  18558. base.GetName(options, name);
  18559. ParameterCollection parameters = this.parameters.Count > 0 ? this.parameters : null;
  18560. // AppendParametersAndReturnType will not emit the paramters
  18561. // prefix and suffix if a null ParameterCollection is provided to it.
  18562. // This prevents a parameterless property from being rendered as MyProperty[]
  18563. Method.AppendParametersAndReturnType(options, parameters, '[', ']', this.Type, name);
  18564. }
  18565. #endif
  18566. }
  18567. public class Variable : Expression{
  18568. private Identifier name;
  18569. #if !MinimalReader
  18570. public TypeNode TypeExpression;
  18571. #endif
  18572. public Variable(NodeType type)
  18573. :base(type){
  18574. }
  18575. /// <summary>The name of a stack location. For example the name of a local variable or the name of a method parameter.</summary>
  18576. public Identifier Name{
  18577. get{return this.name;}
  18578. set{this.name = value;}
  18579. }
  18580. }
  18581. public class Parameter : Variable{
  18582. private AttributeList attributes;
  18583. /// <summary>The (C# custom) attributes of this parameter.</summary>
  18584. public AttributeList Attributes{
  18585. get{
  18586. if (this.attributes != null) return this.attributes;
  18587. return this.attributes = new AttributeList();
  18588. }
  18589. set{this.attributes = value;}
  18590. }
  18591. private Expression defaultValue;
  18592. /// <summary>The value that should be supplied as the argument value of this optional parameter if the source code omits an explicit argument value.</summary>
  18593. public Expression DefaultValue{
  18594. get{return this.defaultValue;}
  18595. set{this.defaultValue = value;}
  18596. }
  18597. private ParameterFlags flags;
  18598. public ParameterFlags Flags{
  18599. get{return this.flags;}
  18600. set{this.flags = value;}
  18601. }
  18602. private MarshallingInformation marshallingInformation;
  18603. public MarshallingInformation MarshallingInformation{
  18604. get{return this.marshallingInformation;}
  18605. set{this.marshallingInformation = value;}
  18606. }
  18607. private Method declaringMethod;
  18608. public Method DeclaringMethod{
  18609. get{return this.declaringMethod;}
  18610. set{this.declaringMethod = value;}
  18611. }
  18612. private int parameterListIndex;
  18613. /// <summary>
  18614. /// Zero based index into a parameter list containing this parameter.
  18615. /// </summary>
  18616. public int ParameterListIndex{
  18617. get{return this.parameterListIndex;}
  18618. set{this.parameterListIndex = value;}
  18619. }
  18620. private int argumentListIndex;
  18621. /// <summary>
  18622. /// Zero based index into the list of arguments on the evaluation stack.
  18623. /// Instance methods have the this object as parameter zero, which means that the first parameter will have value 1, not 0.
  18624. /// </summary>
  18625. public int ArgumentListIndex{
  18626. get{return this.argumentListIndex;}
  18627. set{this.argumentListIndex = value;}
  18628. }
  18629. public Parameter()
  18630. : base(NodeType.Parameter){
  18631. }
  18632. public Parameter(Identifier name, TypeNode type)
  18633. : base(NodeType.Parameter){
  18634. this.Name = name;
  18635. this.Type = type;
  18636. }
  18637. #if !MinimalReader
  18638. public Parameter(AttributeList attributes, ParameterFlags flags, Identifier name, TypeNode type,
  18639. Literal defaultValue, MarshallingInformation marshallingInformation)
  18640. : base(NodeType.Parameter){
  18641. this.attributes = attributes;
  18642. this.defaultValue = defaultValue;
  18643. this.flags = flags;
  18644. this.marshallingInformation = marshallingInformation;
  18645. this.Name = name;
  18646. this.Type = type;
  18647. }
  18648. #endif
  18649. /// <summary>
  18650. /// True if the corresponding argument value is used by the callee. (This need not be the case for a parameter marked as IsOut.)
  18651. /// </summary>
  18652. public virtual bool IsIn{
  18653. get{
  18654. return (this.Flags & ParameterFlags.In) != 0;
  18655. }
  18656. set{
  18657. if (value)
  18658. this.Flags |= ParameterFlags.In;
  18659. else
  18660. this.Flags &= ~ParameterFlags.In;
  18661. }
  18662. }
  18663. /// <summary>
  18664. /// True if the caller can omit providing an argument for this parameter.
  18665. /// </summary>
  18666. public virtual bool IsOptional{
  18667. get{
  18668. return (this.Flags & ParameterFlags.Optional) != 0;
  18669. }
  18670. set{
  18671. if (value)
  18672. this.Flags |= ParameterFlags.Optional;
  18673. else
  18674. this.Flags &= ~ParameterFlags.Optional;
  18675. }
  18676. }
  18677. /// <summary>
  18678. /// True if the corresponding argument must be a left hand expression and will be updated when the call returns.
  18679. /// </summary>
  18680. public virtual bool IsOut{
  18681. get{
  18682. return (this.Flags & ParameterFlags.Out) != 0;
  18683. }
  18684. set{
  18685. if (value)
  18686. this.Flags |= ParameterFlags.Out;
  18687. else
  18688. this.Flags &= ~ParameterFlags.Out;
  18689. }
  18690. }
  18691. #if !MinimalReader
  18692. protected internal TypeNode paramArrayElementType = null;
  18693. /// <summary>
  18694. /// If the parameter is a param array, this returns the element type of the array. If not, it returns null.
  18695. /// </summary>
  18696. public virtual TypeNode GetParamArrayElementType(){
  18697. TypeNode result = this.paramArrayElementType;
  18698. if (result == null){
  18699. AttributeNode attr = this.GetParamArrayAttribute();
  18700. if (attr != null){
  18701. TypeNode t = TypeNode.StripModifiers(this.Type);
  18702. Reference r = t as Reference;
  18703. if (r != null) t = r.ElementType;
  18704. ArrayType arr = t as ArrayType;
  18705. if (arr != null && arr.Rank == 1)
  18706. return this.paramArrayElementType = arr.ElementType;
  18707. }
  18708. this.paramArrayElementType = result = Class.DoesNotExist;
  18709. }
  18710. if (result == Class.DoesNotExist) return null;
  18711. return result;
  18712. }
  18713. protected AttributeNode paramArrayAttribute = null;
  18714. public virtual AttributeNode GetParamArrayAttribute(){
  18715. AttributeNode result = this.paramArrayAttribute;
  18716. if (result == null){
  18717. AttributeList attributes = this.Attributes;
  18718. for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++){
  18719. AttributeNode attr = attributes[i];
  18720. if (attr == null) continue;
  18721. TypeNode attrType = null;
  18722. MemberBinding mb = attr.Constructor as MemberBinding;
  18723. if (mb != null)
  18724. attrType = mb.BoundMember.DeclaringType;
  18725. else{
  18726. Literal lit = attr.Constructor as Literal;
  18727. if (lit == null) continue;
  18728. attrType = lit.Value as TypeNode;
  18729. }
  18730. if (attrType == SystemTypes.ParamArrayAttribute)
  18731. return this.paramArrayAttribute = attr;
  18732. }
  18733. result = this.paramArrayAttribute = AttributeNode.DoesNotExist;
  18734. }
  18735. if (result == AttributeNode.DoesNotExist) return null;
  18736. return result;
  18737. }
  18738. public override bool Equals(object obj) {
  18739. ParameterBinding binding = obj as ParameterBinding;
  18740. return obj == this || binding != null && binding.BoundParameter == this;
  18741. }
  18742. public override int GetHashCode() {
  18743. return base.GetHashCode();
  18744. }
  18745. /// <summary>
  18746. /// Gets the first attribute of the given type in the attribute list of this parameter. Returns null if none found.
  18747. /// This should not be called until the AST containing this member has been processed to replace symbolic references
  18748. /// to members with references to the actual members.
  18749. /// </summary>
  18750. public virtual AttributeNode GetAttribute(TypeNode attributeType) {
  18751. if (attributeType == null) return null;
  18752. AttributeList attributes = this.Attributes;
  18753. for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++) {
  18754. AttributeNode attr = attributes[i];
  18755. if (attr == null) continue;
  18756. MemberBinding mb = attr.Constructor as MemberBinding;
  18757. if (mb != null) {
  18758. if (mb.BoundMember == null) continue;
  18759. if (mb.BoundMember.DeclaringType != attributeType) continue;
  18760. return attr;
  18761. }
  18762. Literal lit = attr.Constructor as Literal;
  18763. if (lit == null) continue;
  18764. if ((lit.Value as TypeNode) != attributeType) continue;
  18765. return attr;
  18766. }
  18767. return null;
  18768. }
  18769. #endif
  18770. #if ExtendedRuntime
  18771. public virtual bool IsUniversallyDelayed {
  18772. get {
  18773. // Special handling of delegate constructors. Their first argument is delayed.
  18774. if (this.DeclaringMethod != null && this.DeclaringMethod.DeclaringType is DelegateNode) {
  18775. if (this.DeclaringMethod.Parameters[0] == this) { // first parameter (not including this)
  18776. return true;
  18777. }
  18778. }
  18779. return (this.GetAttribute(ExtendedRuntimeTypes.DelayedAttribute) != null);
  18780. }
  18781. }
  18782. #endif
  18783. public override string ToString() {
  18784. if (this.Name == null) return "";
  18785. if (this.Type == null) return this.Name.ToString();
  18786. return this.Type.ToString() + " " + this.Name.ToString();
  18787. }
  18788. }
  18789. #if !MinimalReader
  18790. public class ParameterBinding : Parameter, IUniqueKey{
  18791. public Parameter/*!*/ BoundParameter;
  18792. public ParameterBinding(Parameter/*!*/ boundParameter, SourceContext sctx) {
  18793. if (boundParameter == null) throw new ArgumentNullException("boundParameter");
  18794. this.BoundParameter = boundParameter;
  18795. this.SourceContext = sctx;
  18796. this.Type = boundParameter.Type;
  18797. this.Name = boundParameter.Name;
  18798. this.TypeExpression = boundParameter.TypeExpression;
  18799. this.Attributes = boundParameter.Attributes;
  18800. this.DefaultValue = boundParameter.DefaultValue;
  18801. this.Flags = boundParameter.Flags;
  18802. this.MarshallingInformation = boundParameter.MarshallingInformation;
  18803. this.DeclaringMethod = boundParameter.DeclaringMethod;
  18804. this.ParameterListIndex = boundParameter.ParameterListIndex;
  18805. this.ArgumentListIndex = boundParameter.ArgumentListIndex;
  18806. //^ base();
  18807. }
  18808. public override int GetHashCode(){
  18809. return this.BoundParameter.GetHashCode();
  18810. }
  18811. public override bool Equals(object obj){
  18812. ParameterBinding pb = obj as ParameterBinding;
  18813. if (pb != null)
  18814. return this.BoundParameter.Equals(pb.BoundParameter);
  18815. else
  18816. return this.BoundParameter.Equals(obj);
  18817. }
  18818. int IUniqueKey.UniqueId{
  18819. get {return this.BoundParameter.UniqueKey;}
  18820. }
  18821. }
  18822. #endif
  18823. public class Local : Variable{
  18824. #if !MinimalReader
  18825. public Block DeclaringBlock;
  18826. public bool InitOnly;
  18827. public int Index;
  18828. #endif
  18829. public Local()
  18830. : base(NodeType.Local){
  18831. }
  18832. public Local(TypeNode type)
  18833. : base(NodeType.Local){
  18834. this.Name = Identifier.Empty;
  18835. if (type == null) type = CoreSystemTypes.Object;
  18836. this.Type = type;
  18837. }
  18838. public Local(Identifier name, TypeNode type)
  18839. : this(type){
  18840. this.Name = name;
  18841. }
  18842. #if !MinimalReader
  18843. public Local(TypeNode type, SourceContext context)
  18844. : this(Identifier.Empty, type, null){
  18845. this.SourceContext = context;
  18846. }
  18847. public Local(Identifier name, TypeNode type, SourceContext context)
  18848. : this(name, type, null){
  18849. this.SourceContext = context;
  18850. }
  18851. public Local(Identifier name, TypeNode type, Block declaringBlock)
  18852. : base(NodeType.Local){
  18853. this.DeclaringBlock = declaringBlock;
  18854. this.Name = name;
  18855. if (type == null) type = CoreSystemTypes.Object;
  18856. this.Type = type;
  18857. }
  18858. #endif
  18859. private bool pinned;
  18860. public bool Pinned{
  18861. get{return this.pinned;}
  18862. set{this.pinned = value;}
  18863. }
  18864. #if !MinimalReader
  18865. public override bool Equals(object obj){
  18866. LocalBinding binding = obj as LocalBinding;
  18867. return obj == this || binding != null && binding.BoundLocal == this;
  18868. }
  18869. public override int GetHashCode() {
  18870. return base.GetHashCode();
  18871. }
  18872. public override string ToString() {
  18873. if (this.Name == null) return "No name";
  18874. return this.Name.ToString();
  18875. }
  18876. #endif
  18877. }
  18878. #if !MinimalReader
  18879. public class LocalBinding : Local, IUniqueKey{
  18880. public Local/*!*/ BoundLocal;
  18881. public LocalBinding(Local/*!*/ boundLocal, SourceContext sctx) {
  18882. if (boundLocal == null) throw new ArgumentNullException("boundLocal");
  18883. this.BoundLocal = boundLocal;
  18884. //^ base();
  18885. this.SourceContext = sctx;
  18886. this.Type = boundLocal.Type;
  18887. this.Name = boundLocal.Name;
  18888. this.TypeExpression = boundLocal.TypeExpression;
  18889. this.DeclaringBlock = boundLocal.DeclaringBlock;
  18890. this.Pinned = boundLocal.Pinned;
  18891. this.InitOnly = boundLocal.InitOnly;
  18892. this.Index = boundLocal.Index;
  18893. }
  18894. public override int GetHashCode(){
  18895. return this.BoundLocal.GetHashCode();
  18896. }
  18897. public override bool Equals(object obj){
  18898. LocalBinding lb = obj as LocalBinding;
  18899. if (lb != null)
  18900. return this.BoundLocal.Equals(lb.BoundLocal);
  18901. else
  18902. return this.BoundLocal.Equals(obj);
  18903. }
  18904. int IUniqueKey.UniqueId{
  18905. get {return this.BoundLocal.UniqueKey;}
  18906. }
  18907. }
  18908. #endif
  18909. /// <summary>
  18910. /// A named container of types and nested namespaces.
  18911. /// The name of the container implicitly qualifies the names of the contained types and namespaces.
  18912. /// </summary>
  18913. public class Namespace : Member{
  18914. /// <summary>The FullName of the namespace in the form of an Identifier rather than in the form of a string.</summary>
  18915. public Identifier FullNameId;
  18916. #if !MinimalReader
  18917. /// <summary>
  18918. /// Provides alternative names for types and nested namespaces. Useful for introducing shorter names or for resolving name clashes.
  18919. /// The names should be added to the scope associated with this namespace.
  18920. /// </summary>
  18921. public AliasDefinitionList AliasDefinitions;
  18922. /// <summary>
  18923. /// The list of namespaces that are fully contained inside this namespace.
  18924. /// </summary>
  18925. public NamespaceList NestedNamespaces;
  18926. /// <summary>
  18927. /// The Universal Resource Identifier that should be associated with all declarations inside this namespace.
  18928. /// Typically used when the types inside the namespace are serialized as an XML Schema Definition. (XSD)
  18929. /// </summary>
  18930. public Identifier URI;
  18931. /// <summary>
  18932. /// The list of the namespaces of types that should be imported into the scope associated with this namespace.
  18933. /// </summary>
  18934. public UsedNamespaceList UsedNamespaces;
  18935. #endif
  18936. /// <summary>
  18937. /// A delegate that is called the first time Types is accessed. Provides for incremental construction of the namespace node.
  18938. /// </summary>
  18939. public TypeProvider ProvideTypes;
  18940. /// <summary>
  18941. /// Opaque information passed as a parameter to the delegate in ProvideTypes. Typically used to associate this namespace
  18942. /// instance with a helper object.
  18943. /// </summary>
  18944. public object ProviderHandle;
  18945. /// <summary>
  18946. /// A method that fills in the Types property of the given namespace. Must not leave Types null.
  18947. /// </summary>
  18948. public delegate void TypeProvider(Namespace @namespace, object handle);
  18949. protected string fullName;
  18950. protected TypeNodeList types;
  18951. public Namespace()
  18952. : base(NodeType.Namespace){
  18953. }
  18954. public Namespace(Identifier name)
  18955. : base(NodeType.Namespace){
  18956. this.Name = name;
  18957. this.FullNameId = name;
  18958. if (name != null)
  18959. this.fullName = name.ToString();
  18960. }
  18961. #if !MinimalReader
  18962. public Namespace(Identifier name, TypeProvider provideTypes, object providerHandle)
  18963. : base(NodeType.Namespace){
  18964. this.Name = name;
  18965. this.FullNameId = name;
  18966. if (name != null)
  18967. this.fullName = name.ToString();
  18968. this.ProvideTypes = provideTypes;
  18969. this.ProviderHandle = providerHandle;
  18970. }
  18971. public Namespace(Identifier name, Identifier fullName, AliasDefinitionList aliasDefinitions, UsedNamespaceList usedNamespaces,
  18972. NamespaceList nestedNamespaces, TypeNodeList types)
  18973. : base(NodeType.Namespace){
  18974. this.Name = name;
  18975. this.FullNameId = fullName;
  18976. if (fullName != null)
  18977. this.fullName = fullName.ToString();
  18978. this.AliasDefinitions = aliasDefinitions;
  18979. this.NestedNamespaces = nestedNamespaces;
  18980. this.Types = types;
  18981. this.UsedNamespaces = usedNamespaces;
  18982. }
  18983. #endif
  18984. public override string/*!*/ FullName {
  18985. get{return this.fullName == null ? "" : this.fullName;}
  18986. }
  18987. public override bool IsAssembly{get{return false;}}
  18988. public override bool IsCompilerControlled{get{return false;}}
  18989. public override bool IsFamily{get{return false;}}
  18990. public override bool IsFamilyAndAssembly{get{return false;}}
  18991. public override bool IsFamilyOrAssembly{get{return false;}}
  18992. public override bool IsPrivate{get{return !this.IsPublic;}}
  18993. public override bool IsPublic{get{return this.isPublic;}}
  18994. protected internal bool isPublic;
  18995. public override bool IsSpecialName{get{return false;}}
  18996. public override bool IsStatic{get{return false;}}
  18997. public override bool IsVisibleOutsideAssembly{get{return false;}}
  18998. /// <summary>
  18999. /// The list of types contained inside this namespace. If the value of Types is null and the value of ProvideTypes is not null, the
  19000. /// TypeProvider delegate is called to fill in the value of this property.
  19001. /// </summary>
  19002. public TypeNodeList Types{
  19003. get{
  19004. if (this.types == null)
  19005. if (this.ProvideTypes != null)
  19006. lock(this){
  19007. if (this.types == null){
  19008. this.ProvideTypes(this, this.ProviderHandle);
  19009. }
  19010. }
  19011. else
  19012. this.types = new TypeNodeList();
  19013. return this.types;
  19014. }
  19015. set{
  19016. this.types = value;
  19017. }
  19018. }
  19019. }
  19020. #if !MinimalReader
  19021. /// <summary>
  19022. /// The root node of an Abstract Syntax Tree. Typically corresponds to multiple source files compiled to form a single target.
  19023. /// </summary>
  19024. public class Compilation : Node{
  19025. /// <summary>
  19026. /// The compilation parameters that are used for this compilation.
  19027. /// </summary>
  19028. public System.CodeDom.Compiler.CompilerParameters CompilerParameters;
  19029. /// <summary>
  19030. /// The target code object that is produced as a result of this compilation.
  19031. /// </summary>
  19032. public Module TargetModule;
  19033. /// <summary>
  19034. /// A list of all the compilation units (typically source files) that make up this compilation.
  19035. /// </summary>
  19036. public CompilationUnitList CompilationUnits;
  19037. /// <summary>
  19038. /// A scope for symbols that belong to the compilation as a whole. No C# equivalent. Null if not applicable.
  19039. /// </summary>
  19040. public Scope GlobalScope;
  19041. /// <summary>
  19042. /// A list of compilations that produce assemblies and modules that are referenced by this compilation and hence need to be
  19043. /// compiled before this Compilation is compiled. This list is not intended to include already compiled framework assemblies
  19044. /// such as system.dll.
  19045. /// </summary>
  19046. public CompilationList ReferencedCompilations;
  19047. public DateTime LastModified = DateTime.Now;
  19048. public DateTime LastCompiled = DateTime.MinValue;
  19049. public Compilation()
  19050. : base(NodeType.Compilation){
  19051. }
  19052. public Compilation(Module targetModule, CompilationUnitList compilationUnits, System.CodeDom.Compiler.CompilerParameters compilerParameters, Scope globalScope)
  19053. : base(NodeType.Compilation){
  19054. this.CompilationUnits = compilationUnits;
  19055. this.TargetModule = targetModule;
  19056. this.CompilerParameters = compilerParameters;
  19057. this.GlobalScope = globalScope;
  19058. }
  19059. public virtual Compilation CloneCompilationUnits(){
  19060. Compilation clone = (Compilation)base.Clone();
  19061. CompilationUnitList cus = this.CompilationUnits;
  19062. if (cus != null){
  19063. clone.CompilationUnits = cus = cus.Clone();
  19064. for (int i = 0, n = cus.Count; i < n; i++){
  19065. CompilationUnit cu = cus[i];
  19066. if (cu == null) continue;
  19067. cus[i] = cu = (CompilationUnit)cu.Clone();
  19068. cu.Compilation = clone;
  19069. cu.Nodes = null;
  19070. }
  19071. }
  19072. return clone;
  19073. }
  19074. }
  19075. /// <summary>
  19076. /// The root node of an Abstract Syntax Tree. Corresponds to the starting production of the syntax. Equivalent to C# compilation-unit.
  19077. /// Typically a compilation unit corresponds to a single source file.
  19078. /// </summary>
  19079. public class CompilationUnit : Node{
  19080. /// <summary>
  19081. /// An identifier that can be used to retrieve the source text of the compilation unit.
  19082. /// </summary>
  19083. public Identifier Name;
  19084. /// <summary>
  19085. /// An anonymous (name is Identifier.Empty) namespace holding types and nested namespaces.
  19086. /// </summary>
  19087. public NodeList Nodes;
  19088. /// <summary>
  19089. /// The preprocessor symbols that are to treated as defined when compiling this CompilationUnit into the TargetModule.
  19090. /// </summary>
  19091. public Hashtable PreprocessorDefinedSymbols;
  19092. /// <summary>
  19093. /// Pragma warning information.
  19094. /// </summary>
  19095. public TrivialHashtable PragmaWarnInformation;
  19096. /// <summary>
  19097. /// The compilation of which this unit forms a part.
  19098. /// </summary>
  19099. public Compilation Compilation;
  19100. public CompilationUnit()
  19101. : base(NodeType.CompilationUnit){
  19102. }
  19103. public CompilationUnit(Identifier name)
  19104. : base(NodeType.CompilationUnit){
  19105. this.Name = name;
  19106. }
  19107. }
  19108. public class CompilationUnitSnippet : CompilationUnit{
  19109. public DateTime LastModified = DateTime.Now;
  19110. public IParserFactory ParserFactory;
  19111. public Method ChangedMethod;
  19112. public int OriginalEndPosOfChangedMethod;
  19113. public CompilationUnitSnippet(){
  19114. this.NodeType = NodeType.CompilationUnitSnippet;
  19115. }
  19116. public CompilationUnitSnippet(Identifier name, IParserFactory parserFactory, SourceContext sctx){
  19117. this.NodeType = NodeType.CompilationUnitSnippet;
  19118. this.Name = name;
  19119. this.ParserFactory = parserFactory;
  19120. this.SourceContext = sctx;
  19121. }
  19122. }
  19123. public abstract class Composer{
  19124. public abstract Node Compose (Node node, Composer context, bool hasContextReference, Class scope);
  19125. private class NullComposer: Composer{
  19126. public override Node Compose(Node node, Composer context, bool hasContextReference, Class scope){
  19127. return node;
  19128. }
  19129. }
  19130. public static readonly Composer Null = new NullComposer();
  19131. }
  19132. public class Composition: Expression{
  19133. public Expression Expression;
  19134. public Composer Composer;
  19135. public Class Scope;
  19136. public Composition(Expression exp, Composer composer, Class scope)
  19137. : base(NodeType.Composition){
  19138. this.Expression = exp;
  19139. this.Composer = composer;
  19140. this.Scope = scope;
  19141. if (exp != null) this.Type = exp.Type;
  19142. }
  19143. }
  19144. #endif
  19145. #if ExtendedRuntime
  19146. // query nodes
  19147. public class QueryAlias: QueryExpression{
  19148. public Identifier Name;
  19149. public Expression Expression;
  19150. public QueryAlias(): base(NodeType.QueryAlias){
  19151. }
  19152. }
  19153. public abstract class Accessor{
  19154. }
  19155. public class MemberAccessor: Accessor{
  19156. public Member Member;
  19157. public TypeNode Type;
  19158. public bool Yield;
  19159. public Accessor Next;
  19160. public MemberAccessor(Member member){
  19161. this.Member = member;
  19162. }
  19163. }
  19164. public class SequenceAccessor: Accessor{
  19165. public ArrayList Accessors; // member accessors only
  19166. public SequenceAccessor(){
  19167. this.Accessors = new ArrayList();
  19168. }
  19169. }
  19170. public class SwitchAccessor: Accessor{
  19171. public TypeUnion Type;
  19172. public Hashtable Accessors; // key == type
  19173. public SwitchAccessor(){
  19174. this.Accessors = new Hashtable();
  19175. }
  19176. }
  19177. public enum Cardinality{
  19178. None, // reference type
  19179. One, // !
  19180. ZeroOrOne, // ?
  19181. OneOrMore, // +
  19182. ZeroOrMore // *
  19183. }
  19184. public class QueryAxis: QueryExpression{
  19185. public Expression Source;
  19186. public bool IsDescendant;
  19187. public Identifier Name;
  19188. public Identifier Namespace;
  19189. public TypeNode TypeTest;
  19190. public Accessor AccessPlan;
  19191. public Cardinality Cardinality;
  19192. public int YieldCount;
  19193. public TypeNodeList YieldTypes;
  19194. public bool IsCyclic;
  19195. public bool IsIterative;
  19196. public QueryAxis (Expression source, bool isDescendant, Identifier name, TypeNode typeTest)
  19197. : base(NodeType.QueryAxis){
  19198. this.Source = source;
  19199. this.IsDescendant = isDescendant;
  19200. this.Name = name;
  19201. this.TypeTest = typeTest;
  19202. }
  19203. }
  19204. public class QueryAggregate: QueryExpression{
  19205. public Identifier Name;
  19206. public TypeNode AggregateType;
  19207. public Expression Expression;
  19208. public ContextScope Context;
  19209. public QueryGroupBy Group;
  19210. public QueryAggregate(): base(NodeType.QueryAggregate){
  19211. }
  19212. }
  19213. public class ContextScope{
  19214. public ContextScope Previous;
  19215. public TypeNode Type;
  19216. public Expression Target;
  19217. public Expression Position;
  19218. public Block PreFilter;
  19219. public Block PostFilter;
  19220. public ContextScope(ContextScope previous, TypeNode type){
  19221. this.Previous = previous;
  19222. this.Type = type;
  19223. }
  19224. }
  19225. public class QueryContext: QueryExpression{
  19226. public ContextScope Scope;
  19227. public QueryContext()
  19228. : base(NodeType.QueryContext){
  19229. }
  19230. public QueryContext(ContextScope scope): base(NodeType.QueryContext){
  19231. this.Scope = scope;
  19232. if (scope != null) this.Type = scope.Type;
  19233. }
  19234. }
  19235. public class QueryDelete: QueryExpression{
  19236. public Expression Source;
  19237. public Expression Target;
  19238. public ContextScope Context;
  19239. public Expression SourceEnumerable;
  19240. public QueryDelete(): base(NodeType.QueryDelete){
  19241. }
  19242. }
  19243. public class QueryDistinct: QueryExpression{
  19244. public Expression Source;
  19245. public ContextScope Context;
  19246. public QueryGroupBy Group;
  19247. public Expression GroupTarget;
  19248. public QueryDistinct(): base(NodeType.QueryDistinct){
  19249. }
  19250. }
  19251. public class QueryDifference: QueryExpression{
  19252. public Expression LeftSource;
  19253. public Expression RightSource;
  19254. public QueryDifference() : base(NodeType.QueryDifference){
  19255. }
  19256. }
  19257. public class QueryExists: QueryExpression{
  19258. public Expression Source;
  19259. public QueryExists() : base(NodeType.QueryExists){
  19260. }
  19261. }
  19262. public abstract class QueryExpression: Expression{
  19263. protected QueryExpression(NodeType nt): base(nt){
  19264. }
  19265. }
  19266. public class QueryFilter: QueryExpression{
  19267. public Expression Source;
  19268. public Expression Expression;
  19269. public ContextScope Context;
  19270. public QueryFilter(): base(NodeType.QueryFilter){
  19271. }
  19272. public QueryFilter (Expression source, Expression filter): this(){
  19273. this.Source = source;
  19274. this.Expression = filter;
  19275. }
  19276. }
  19277. public class QueryYielder: Statement{
  19278. public Expression Source;
  19279. public Expression Target;
  19280. public Expression State;
  19281. public Block Body;
  19282. public QueryYielder(): base(NodeType.QueryYielder){
  19283. }
  19284. }
  19285. public class QueryGeneratedType: Statement{
  19286. public TypeNode Type;
  19287. public QueryGeneratedType(TypeNode type): base(NodeType.QueryGeneratedType){
  19288. this.Type = type;
  19289. }
  19290. }
  19291. public class QueryGroupBy: QueryExpression{
  19292. public Expression Source;
  19293. public ContextScope GroupContext;
  19294. public ExpressionList GroupList;
  19295. public ExpressionList AggregateList;
  19296. public Expression Having;
  19297. public ContextScope HavingContext;
  19298. public QueryGroupBy(): base(NodeType.QueryGroupBy){
  19299. this.GroupList = new ExpressionList();
  19300. this.AggregateList = new ExpressionList();
  19301. }
  19302. }
  19303. public class QueryInsert: QueryExpression{
  19304. public Expression Location;
  19305. public QueryInsertPosition Position;
  19306. public ExpressionList InsertList;
  19307. public ExpressionList HintList;
  19308. public ContextScope Context;
  19309. public bool IsBracket;
  19310. public QueryInsert(): base(NodeType.QueryInsert){
  19311. this.InsertList = new ExpressionList();
  19312. this.HintList = new ExpressionList();
  19313. }
  19314. }
  19315. public enum QueryInsertPosition{
  19316. After,
  19317. At,
  19318. Before,
  19319. First,
  19320. In,
  19321. Last
  19322. }
  19323. public class QueryIntersection: QueryExpression{
  19324. public Expression LeftSource;
  19325. public Expression RightSource;
  19326. public QueryIntersection(): base(NodeType.QueryIntersection){
  19327. }
  19328. }
  19329. public class QueryScope: BlockScope{
  19330. public QueryScope(Scope/*!*/ parentScope)
  19331. : base(parentScope, null) {
  19332. }
  19333. }
  19334. public class QueryIterator: QueryAlias{
  19335. public TypeNode ElementType;
  19336. public TypeNode TypeExpression;
  19337. public ExpressionList HintList;
  19338. public QueryIterator(): base(){
  19339. this.NodeType = NodeType.QueryIterator;
  19340. this.HintList = new ExpressionList();
  19341. }
  19342. }
  19343. public class QueryJoin: QueryExpression{
  19344. public Expression LeftOperand;
  19345. public Expression RightOperand;
  19346. public QueryJoinType JoinType;
  19347. public Expression JoinExpression;
  19348. public ContextScope JoinContext;
  19349. public QueryJoin(): base(NodeType.QueryJoin){
  19350. }
  19351. }
  19352. public enum QueryJoinType{
  19353. Inner,
  19354. LeftOuter,
  19355. RightOuter,
  19356. FullOuter
  19357. }
  19358. public class QueryLimit: QueryExpression{
  19359. public Expression Source;
  19360. public Expression Expression;
  19361. public bool IsPercent;
  19362. public bool IsWithTies;
  19363. public QueryLimit(): base(NodeType.QueryLimit){
  19364. }
  19365. }
  19366. public class QueryOrderBy: QueryExpression{
  19367. public Expression Source;
  19368. public ContextScope Context;
  19369. public ExpressionList OrderList;
  19370. public QueryOrderBy(): base(NodeType.QueryOrderBy){
  19371. this.OrderList = new ExpressionList();
  19372. }
  19373. }
  19374. public enum QueryOrderType{
  19375. Ascending,
  19376. Descending,
  19377. Document
  19378. }
  19379. public class QueryOrderItem: QueryExpression{
  19380. public Expression Expression;
  19381. public QueryOrderType OrderType = QueryOrderType.Ascending;
  19382. public QueryOrderItem(): base(NodeType.QueryOrderItem){
  19383. }
  19384. }
  19385. public class QueryPosition: QueryExpression{
  19386. public ContextScope Context;
  19387. public QueryPosition(ContextScope context): base(NodeType.QueryPosition){
  19388. this.Context = context;
  19389. this.Type = CoreSystemTypes.Int32;
  19390. }
  19391. public static readonly Identifier Id = Identifier.For("position");
  19392. }
  19393. public class QueryProject: QueryExpression{
  19394. public Expression Source;
  19395. public ContextScope Context;
  19396. public ExpressionList ProjectionList;
  19397. public TypeNode ProjectedType;
  19398. public MemberList Members;
  19399. public QueryProject(): base(NodeType.QueryProject){
  19400. this.ProjectionList = new ExpressionList();
  19401. }
  19402. }
  19403. public class QueryQuantifiedExpression: QueryExpression{
  19404. public QueryQuantifier Left;
  19405. public QueryQuantifier Right;
  19406. public Expression Expression;
  19407. public QueryQuantifiedExpression(): base(NodeType.QueryQuantifiedExpression){
  19408. }
  19409. }
  19410. public class QueryQuantifier: QueryExpression{
  19411. public Expression Expression;
  19412. public Expression Target;
  19413. public QueryQuantifier(NodeType nt): base(nt){
  19414. }
  19415. }
  19416. public class QuerySingleton: QueryExpression{
  19417. public Expression Source;
  19418. public QuerySingleton(): base(NodeType.QuerySingleton){
  19419. }
  19420. }
  19421. public class QuerySelect: QueryExpression{
  19422. public Expression Source;
  19423. public QueryCursorDirection Direction;
  19424. public QueryCursorAccess Access;
  19425. public QuerySelect(Expression source): base(NodeType.QuerySelect){
  19426. if (source != null){
  19427. this.Source = source;
  19428. this.Type = source.Type;
  19429. }
  19430. }
  19431. }
  19432. public enum QueryCursorDirection{
  19433. ForwardOnly,
  19434. Scrollable
  19435. }
  19436. public enum QueryCursorAccess{
  19437. ReadOnly,
  19438. Updatable
  19439. }
  19440. public abstract class QueryStatement: Statement{
  19441. protected QueryStatement(NodeType nt): base(nt){
  19442. }
  19443. }
  19444. public class QueryTypeFilter: QueryExpression{
  19445. public Expression Source;
  19446. public TypeNode Constraint;
  19447. public QueryTypeFilter(): base(NodeType.QueryTypeFilter){
  19448. }
  19449. }
  19450. public class QueryUnion: QueryExpression{
  19451. public Expression LeftSource;
  19452. public Expression RightSource;
  19453. public QueryUnion() : base(NodeType.QueryUnion){
  19454. }
  19455. }
  19456. public class QueryUpdate: QueryExpression{
  19457. public Expression Source;
  19458. public ExpressionList UpdateList;
  19459. public ContextScope Context;
  19460. public QueryUpdate() : base(NodeType.QueryUpdate){
  19461. this.UpdateList = new ExpressionList();
  19462. }
  19463. }
  19464. public class QueryTransact: Statement{
  19465. public Expression Source;
  19466. public Expression Isolation;
  19467. public Block Body;
  19468. public Block CommitBody;
  19469. public Block RollbackBody;
  19470. public Expression Transaction;
  19471. public QueryTransact(): base(NodeType.QueryTransact){
  19472. }
  19473. }
  19474. public class QueryCommit: Statement{
  19475. public QueryCommit(): base(NodeType.QueryCommit){
  19476. }
  19477. }
  19478. public class QueryRollback: Statement{
  19479. public QueryRollback(): base(NodeType.QueryRollback){
  19480. }
  19481. }
  19482. #endif
  19483. #if !MinimalReader
  19484. /// <summary>
  19485. /// An object that knows how to produce a particular scope's view of a type.
  19486. /// </summary>
  19487. public class TypeViewer {
  19488. /// <summary>
  19489. /// Return a scope's view of the argument type, where the scope's view is represented
  19490. /// by a type viewer.
  19491. /// [The identity function, except for dialects (e.g. Extensible Sing#) that allow
  19492. /// extensions and differing views of types].
  19493. /// Defined as a static method to allow the type viewer to be null,
  19494. /// meaning an identity-function view.
  19495. /// </summary>
  19496. public static TypeNode/*!*/ GetTypeView(TypeViewer typeViewer, TypeNode/*!*/ type) {
  19497. return typeViewer == null ? type.EffectiveTypeNode : typeViewer.GetTypeView(type);
  19498. }
  19499. /// <summary>
  19500. /// Return the typeViewer's view of the argument type. Overridden by subclasses
  19501. /// that support non-identity-function type viewers, e.g. Extensible Sing#.
  19502. /// </summary>
  19503. protected virtual TypeNode/*!*/ GetTypeView(TypeNode/*!*/ type) {
  19504. return type.EffectiveTypeNode;
  19505. }
  19506. }
  19507. #endif
  19508. #if WHIDBEY
  19509. static
  19510. #endif
  19511. class PlatformHelpers {
  19512. internal static bool TryParseInt32(String s, out Int32 result) {
  19513. #if WHIDBEY
  19514. return Int32.TryParse(s, NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out result);
  19515. #else
  19516. result = 0;
  19517. bool succeeded = false;
  19518. try {
  19519. result = Int32.Parse(s, NumberFormatInfo.InvariantInfo);
  19520. succeeded = true;
  19521. }catch(ArgumentException){
  19522. }catch(FormatException){
  19523. }catch(OverflowException){}
  19524. return succeeded;
  19525. #endif
  19526. }
  19527. internal static int StringCompareOrdinalIgnoreCase(string strA, int indexA, string strB, int indexB, int length) {
  19528. #if WHIDBEY
  19529. return string.Compare(strA, indexA, strB, indexB, length, StringComparison.OrdinalIgnoreCase);
  19530. #else
  19531. return string.Compare(strA, indexA, strB, indexB, length, true, CultureInfo.InvariantCulture);
  19532. #endif
  19533. }
  19534. internal static int StringCompareOrdinalIgnoreCase(string strA, string strB) {
  19535. #if WHIDBEY
  19536. return string.Compare(strA, strB, StringComparison.OrdinalIgnoreCase);
  19537. #else
  19538. return string.Compare(strA, strB, true, CultureInfo.InvariantCulture);
  19539. #endif
  19540. }
  19541. }
  19542. #if FxCop
  19543. public class CatchNode : Statement{
  19544. private Block block;
  19545. private TypeNode type;
  19546. private Expression variable;
  19547. private Filter filter;
  19548. internal int handlerEnd;
  19549. internal CatchNode()
  19550. : base(NodeType.Catch){
  19551. }
  19552. internal CatchNode(Block block, Expression variable, TypeNode type)
  19553. : this(block, variable, type, null){
  19554. }
  19555. internal CatchNode(Block block, Expression variable, TypeNode type, Filter filter)
  19556. : base(NodeType.Catch){
  19557. this.block = block;
  19558. this.variable = variable;
  19559. this.type = type;
  19560. this.filter = filter;
  19561. }
  19562. public Block Block{
  19563. get{return this.block;}
  19564. internal set{this.block = value;}
  19565. }
  19566. public Filter Filter{
  19567. get{return this.filter;}
  19568. internal set{this.filter = value;}
  19569. }
  19570. public TypeNode Type{
  19571. get{return this.type;}
  19572. internal set{this.type = value;}
  19573. }
  19574. public Expression Variable{
  19575. get{return this.variable;}
  19576. internal set{this.variable = value;}
  19577. }
  19578. }
  19579. public class FinallyNode : Statement{
  19580. private Block block;
  19581. internal int handlerEnd;
  19582. internal FinallyNode()
  19583. : base(NodeType.Finally){
  19584. }
  19585. internal FinallyNode(Block block)
  19586. : base(NodeType.Finally){
  19587. this.block = block;
  19588. }
  19589. public Block Block{
  19590. get{return this.block;}
  19591. internal set{this.block = value;}
  19592. }
  19593. }
  19594. public class TryNode : Statement {
  19595. private CatchNodeCollection catchers = new CatchNodeCollection();
  19596. private FaultHandler faultHandler;
  19597. private FinallyNode finallyClause;
  19598. private Block block;
  19599. internal TryNode()
  19600. : base(NodeType.Try) {
  19601. }
  19602. internal TryNode(Block block, CatchNodeCollection catchers, FaultHandler faultHandler, FinallyNode @finally)
  19603. : base(NodeType.Try) {
  19604. this.catchers = catchers;
  19605. this.faultHandler = faultHandler;
  19606. this.finallyClause = @finally;
  19607. this.block = block;
  19608. }
  19609. internal int tryEnd;
  19610. internal int handlersEnd;
  19611. public CatchNodeCollection Catchers {
  19612. get { return this.catchers; }
  19613. internal set { this.catchers = value; }
  19614. }
  19615. public FaultHandler FaultHandler {
  19616. get { return this.faultHandler; }
  19617. internal set { this.faultHandler = value; }
  19618. }
  19619. public FinallyNode Finally {
  19620. get { return this.finallyClause; }
  19621. internal set { this.finallyClause = value; }
  19622. }
  19623. public Block Block {
  19624. [DebuggerStepThrough] get { return this.block; }
  19625. [DebuggerStepThrough] internal set { this.block = value; }
  19626. }
  19627. }
  19628. public abstract class FormatOptions
  19629. {
  19630. internal Options m_options;
  19631. protected FormatOptions() { }
  19632. internal void SetOptions(Options options, bool enable)
  19633. {
  19634. if (enable)
  19635. {
  19636. this.m_options |= options;
  19637. return;
  19638. }
  19639. this.m_options &= ~options;
  19640. }
  19641. internal bool IsSet(Options options)
  19642. {
  19643. return (this.m_options & options) == options;
  19644. }
  19645. [Flags]
  19646. internal enum Options
  19647. {
  19648. None = 0x0,
  19649. InsertSpacesBetweenParameters = 0x1,
  19650. InsertSpacesBetweenTypeParameters = 0x2,
  19651. InsertSpacesBetweenMethodTypeParameters = 0x4,
  19652. ShowGenericTypeArity = 0x8,
  19653. ShowGenericMethodTypeParameterNames = 0x10,
  19654. ShowGenericTypeParameterNames = 0x20,
  19655. ShowTypeModifiers = 0x40,
  19656. ShowParameterNames = 0x80
  19657. }
  19658. }
  19659. internal class MemberFormat : FormatOptions
  19660. {
  19661. TypeFormat m_declaringTypeFormat;
  19662. TypeFormat m_returnTypeFormat;
  19663. ParameterFormat m_parameterFormat;
  19664. public MemberFormat()
  19665. {
  19666. this.m_declaringTypeFormat = new TypeFormat();
  19667. this.m_returnTypeFormat = new TypeFormat();
  19668. this.m_parameterFormat = new ParameterFormat();
  19669. }
  19670. public TypeFormat Type
  19671. {
  19672. get { return this.m_declaringTypeFormat; }
  19673. }
  19674. public TypeFormat ReturnType
  19675. {
  19676. get { return this.m_returnTypeFormat; }
  19677. }
  19678. public ParameterFormat Parameters
  19679. {
  19680. get { return this.m_parameterFormat; }
  19681. }
  19682. public bool ShowGenericMethodTypeParameterNames
  19683. {
  19684. get { return IsSet(Options.ShowGenericMethodTypeParameterNames); }
  19685. set { SetOptions(Options.ShowGenericMethodTypeParameterNames, value); }
  19686. }
  19687. public bool InsertSpacesBetweenMethodTypeParameters
  19688. {
  19689. get { return IsSet(Options.InsertSpacesBetweenMethodTypeParameters); }
  19690. set { SetOptions(Options.InsertSpacesBetweenMethodTypeParameters, value); }
  19691. }
  19692. }
  19693. internal class ParameterFormat : TypeFormat
  19694. {
  19695. public ParameterFormat() { }
  19696. public bool InsertSpacesBetweenParameters
  19697. {
  19698. get { return IsSet(Options.InsertSpacesBetweenParameters); }
  19699. set { SetOptions(Options.InsertSpacesBetweenParameters, value); }
  19700. }
  19701. public bool ShowParameterNames
  19702. {
  19703. get { return IsSet(Options.ShowParameterNames); }
  19704. set { SetOptions(Options.ShowParameterNames, value); }
  19705. }
  19706. }
  19707. internal class TypeFormat : FormatOptions
  19708. {
  19709. private TypeNameFormat m_typeName;
  19710. public TypeFormat() { }
  19711. public TypeFormat Clone()
  19712. {
  19713. TypeFormat clone = new TypeFormat();
  19714. clone.m_typeName = this.m_typeName;
  19715. clone.m_options = this.m_options;
  19716. return clone;
  19717. }
  19718. public bool InsertSpacesBetweenTypeParameters
  19719. {
  19720. get { return IsSet(Options.InsertSpacesBetweenTypeParameters); }
  19721. set { SetOptions(Options.InsertSpacesBetweenTypeParameters, value); }
  19722. }
  19723. public bool ShowGenericTypeArity
  19724. {
  19725. get { return IsSet(Options.ShowGenericTypeArity); }
  19726. set { SetOptions(Options.ShowGenericTypeArity, value); }
  19727. }
  19728. public bool ShowGenericTypeParameterNames
  19729. {
  19730. get { return IsSet(Options.ShowGenericTypeParameterNames); }
  19731. set { SetOptions(Options.ShowGenericTypeParameterNames, value); }
  19732. }
  19733. public bool ShowTypeModifiers
  19734. {
  19735. get { return IsSet(Options.ShowTypeModifiers); }
  19736. set { SetOptions(Options.ShowTypeModifiers, value); }
  19737. }
  19738. public TypeNameFormat TypeName
  19739. {
  19740. get { return this.m_typeName; }
  19741. set { this.m_typeName = value; }
  19742. }
  19743. }
  19744. internal enum TypeNameFormat
  19745. {
  19746. None = 0,
  19747. InnermostNested,
  19748. Short,
  19749. FullyQualified
  19750. }
  19751. #endif
  19752. }