summaryrefslogtreecommitdiffstats
path: root/tools/Sandcastle/Source/CCI/Nodes.cs
diff options
context:
space:
mode:
Diffstat (limited to 'tools/Sandcastle/Source/CCI/Nodes.cs')
-rw-r--r--tools/Sandcastle/Source/CCI/Nodes.cs21996
1 files changed, 21996 insertions, 0 deletions
diff --git a/tools/Sandcastle/Source/CCI/Nodes.cs b/tools/Sandcastle/Source/CCI/Nodes.cs
new file mode 100644
index 0000000..dd251b3
--- /dev/null
+++ b/tools/Sandcastle/Source/CCI/Nodes.cs
@@ -0,0 +1,21996 @@
+// Copyright © Microsoft Corporation.
+// This source file is subject to the Microsoft Permissive License.
+// See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.
+// All other rights reserved.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Collections.Specialized;
+#if FxCop
+using AssemblyReferenceList = Microsoft.Cci.AssemblyReferenceCollection;
+using AttributeList = Microsoft.Cci.AttributeNodeCollection;
+using BlockList = Microsoft.Cci.BlockCollection;
+using ExpressionList = Microsoft.Cci.ExpressionCollection;
+using InstructionList = Microsoft.Cci.InstructionCollection;
+using Int32List = System.Collections.Generic.List<int>;
+using InterfaceList = Microsoft.Cci.InterfaceCollection;
+using MemberList = Microsoft.Cci.MemberCollection;
+using MethodList = Microsoft.Cci.MethodCollection;
+using ModuleReferenceList = Microsoft.Cci.ModuleReferenceCollection;
+using NamespaceList = Microsoft.Cci.NamespaceCollection;
+using ParameterList = Microsoft.Cci.ParameterCollection;
+using ResourceList = Microsoft.Cci.ResourceCollection;
+using SecurityAttributeList = Microsoft.Cci.SecurityAttributeCollection;
+using StatementList = Microsoft.Cci.StatementCollection;
+using TypeNodeList = Microsoft.Cci.TypeNodeCollection;
+using Win32ResourceList = Microsoft.Cci.Win32ResourceCollection;
+using Module = Microsoft.Cci.ModuleNode;
+using Class = Microsoft.Cci.ClassNode;
+using Interface = Microsoft.Cci.InterfaceNode;
+using Property = Microsoft.Cci.PropertyNode;
+using Event = Microsoft.Cci.EventNode;
+using Return = Microsoft.Cci.ReturnNode;
+using Throw = Microsoft.Cci.ThrowNode;
+#endif
+#if UseSingularityPDB
+using Microsoft.Singularity.PdbInfo;
+#endif
+#if CCINamespace
+using Cci = Microsoft.Cci;
+using Microsoft.Cci.Metadata;
+using Metadata = Microsoft.Cci.Metadata;
+#else
+using Cci = System.Compiler;
+using System.Compiler.Metadata;
+using Metadata = System.Compiler.Metadata;
+#endif
+using System.Diagnostics;
+using System.IO;
+using System.Text;
+#if !NoXml
+using System.Xml;
+#endif
+
+using BindingFlags = System.Reflection.BindingFlags;
+
+#if CCINamespace
+namespace Microsoft.Cci{
+#else
+namespace System.Compiler
+{
+#endif
+#if !FxCop
+ /// <summary>
+ /// This interface can be used to link an arbitrary source text provider into an IR tree via a DocumentText instance.
+ /// </summary>
+ public interface ISourceText
+ {
+ /// <summary>
+ /// The number of characters in the source text.
+ /// A "character" corresponds to a System.Char which is actually a Unicode UTF16 code point to be precise.
+ /// </summary>
+ int Length { get; }
+ /// <summary>
+ /// Retrieves a substring from this instance. The substring starts with the character at the specified index and has a specified length.
+ /// </summary>
+ string Substring(int startIndex, int length);
+ /// <summary>
+ /// Retrieves the character at the given position. The first character is at position zero.
+ /// </summary>
+ char this[int position] { get; }
+ /// <summary>
+ /// Indicates that the text has been fully scanned and futher references to the text are expected to be infrequent.
+ /// The underlying object can now choose to clear cached information if it comes under resource pressure.
+ /// </summary>
+ void MakeCollectible();
+ }
+ public unsafe interface ISourceTextBuffer : ISourceText
+ {
+ /// <summary>
+ /// Returns null unless the implementer is based on an ASCII buffer that stays alive as long at the implementer itself.
+ /// An implementer that returns a non-null value is merely a wrapper to keep the buffer alive. No further methods will
+ /// be called on the interface in this case.
+ /// </summary>
+ byte* Buffer { get; }
+ }
+#endif
+#if !MinimalReader
+ /// <summary>
+ /// Use this after a source text has already been scanned and parsed. This allows the source text to get released
+ /// if there is memory pressure, while still allowing portions of it to be retrieved on demand. This is useful when
+ /// a large number of source files are read in, but only infrequent references are made to them.
+ /// </summary>
+ public sealed class CollectibleSourceText : ISourceText
+ {
+ private string/*!*/ filePath;
+ private WeakReference/*!*/ fileContent;
+ private int length;
+
+ public CollectibleSourceText(string/*!*/ filePath, int length)
+ {
+ this.filePath = filePath;
+ this.fileContent = new WeakReference(null);
+ this.length = length;
+ //^ base();
+ }
+ public CollectibleSourceText(string/*!*/ filePath, string fileContent)
+ {
+ this.filePath = filePath;
+ this.fileContent = new WeakReference(fileContent);
+ this.length = fileContent == null ? 0 : fileContent.Length;
+ //^ base();
+ }
+ private string/*!*/ ReadFile()
+ {
+ string content = string.Empty;
+ try
+ {
+ StreamReader sr = new StreamReader(filePath);
+ content = sr.ReadToEnd();
+ this.length = content.Length;
+ sr.Close();
+ }
+ catch { }
+ return content;
+ }
+ public string/*!*/ GetSourceText()
+ {
+ string source = (string)this.fileContent.Target;
+ if (source != null) return source;
+ source = this.ReadFile();
+ this.fileContent.Target = source;
+ return source;
+ }
+
+ int ISourceText.Length { get { return this.length; } }
+ string ISourceText.Substring(int startIndex, int length)
+ {
+ return this.GetSourceText().Substring(startIndex, length);
+ }
+ char ISourceText.this[int index]
+ {
+ get
+ {
+ return this.GetSourceText()[index];
+ }
+ }
+ void ISourceText.MakeCollectible()
+ {
+ this.fileContent.Target = null;
+ }
+ }
+ /// <summary>
+ /// This class is used to wrap the string contents of a source file with an ISourceText interface. It is used while compiling
+ /// a project the first time in order to obtain a symbol table. After that the StringSourceText instance is typically replaced with
+ /// a CollectibleSourceText instance, so that the actual source text string can be collected. When a file is edited,
+ /// 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.
+ /// </summary>
+ public sealed class StringSourceText : ISourceText
+ {
+ /// <summary>
+ /// The wrapped string used to implement ISourceText. Use this value when unwrapping.
+ /// </summary>
+ public readonly string/*!*/ SourceText;
+ /// <summary>
+ /// True when the wrapped string is the contents of a file. Typically used to check if it safe to replace this
+ /// StringSourceText instance with a CollectibleSourceText instance.
+ /// </summary>
+ public bool IsSameAsFileContents;
+
+ public StringSourceText(string/*!*/ sourceText, bool isSameAsFileContents)
+ {
+ this.SourceText = sourceText;
+ this.IsSameAsFileContents = isSameAsFileContents;
+ //^ base();
+ }
+ int ISourceText.Length { get { return this.SourceText.Length; } }
+ string ISourceText.Substring(int startIndex, int length)
+ {
+ return this.SourceText.Substring(startIndex, length);
+ }
+ char ISourceText.this[int index]
+ {
+ get
+ {
+ return this.SourceText[index];
+ }
+ }
+ void ISourceText.MakeCollectible()
+ {
+ }
+ }
+#endif
+#if !FxCop
+ /// <summary>
+ /// This class provides a uniform interface to program sources provided in the form of Unicode strings,
+ /// unsafe pointers to ascii buffers (as obtained from a memory mapped file, for instance) as well as
+ /// arbitrary source text providers that implement the ISourceText interface.
+ /// </summary>
+ public sealed unsafe class DocumentText
+ {
+ /// <summary>
+ /// If this is not null it is used to obtain 8-bit ASCII characters.
+ /// </summary>
+ public byte* AsciiStringPtr;
+ /// <summary>
+ /// If this is not null it represents a Unicode string encoded as UTF16.
+ /// </summary>
+ public string Source;
+ /// <summary>
+ /// If this is not null the object implement ISourceText provides some way to get at individual characters and substrings.
+ /// </summary>
+ public ISourceText TextProvider;
+ /// <summary>
+ /// The number of characters in the source document.
+ /// A "character" corresponds to a System.Char which is actually a Unicode UTF16 code point to be precise.
+ /// </summary>
+ public int Length;
+ public DocumentText(string source)
+ {
+ if (source == null) { Debug.Assert(false); return; }
+ this.Source = source;
+ this.Length = source.Length;
+ }
+ public DocumentText(ISourceText textProvider)
+ {
+ if (textProvider == null) { Debug.Assert(false); return; }
+ this.TextProvider = textProvider;
+ this.Length = textProvider.Length;
+ }
+ public unsafe DocumentText(ISourceTextBuffer textProvider)
+ {
+ if (textProvider == null) { Debug.Assert(false); return; }
+ this.TextProvider = textProvider;
+ this.AsciiStringPtr = textProvider.Buffer;
+ this.Length = textProvider.Length;
+ }
+ /// <summary>
+ /// Compare this.Substring(offset, length) for equality with str.
+ /// Call this only if str.Length is known to be equal to length.
+ /// </summary>
+ public bool Equals(string str, int position, int length)
+ { //TODO: (int position, int length, string str)
+ if (str == null) { Debug.Assert(false); return false; }
+ if (str.Length != length) { Debug.Assert(false); return false; }
+ if (position < 0 || position + length > this.Length) { Debug.Assert(false); return false; }
+ unsafe
+ {
+ byte* p = this.AsciiStringPtr;
+ if (p != null)
+ {
+ for (int i = position, j = 0; j < length; i++, j++)
+ if (((char)*(p + i)) != str[j]) return false;
+ return true;
+ }
+ }
+ string source = this.Source;
+ if (source != null)
+ {
+ for (int i = position, j = 0; j < length; i++, j++)
+ if (source[i] != str[j]) return false;
+ return true;
+ }
+ ISourceText myProvider = this.TextProvider;
+ if (myProvider == null) { Debug.Assert(false); return false; }
+ for (int i = position, j = 0; j < length; i++, j++)
+ if (myProvider[i] != str[j]) return false;
+ return true;
+ }
+ /// <summary>
+ /// Compares the substring of the specificied length starting at offset, with the substring in DocumentText starting at textOffset.
+ /// </summary>
+ /// <param name="offset">The index of the first character of the substring of this DocumentText.</param>
+ /// <param name="text">The Document text with the substring being compared to.</param>
+ /// <param name="textOffset">The index of the first character of the substring of the DocumentText being compared to.</param>
+ /// <param name="length">The number of characters in the substring being compared.</param>
+ /// <returns></returns>
+ public bool Equals(int offset, DocumentText text, int textOffset, int length)
+ { //TODO: (int position, int length, DocumentText text, int textPosition)
+ if (offset < 0 || length < 0 || offset + length > this.Length) { Debug.Assert(false); return false; }
+ if (textOffset < 0 || text == null || textOffset + length > text.Length) { Debug.Assert(false); return false; }
+ unsafe
+ {
+ byte* p = this.AsciiStringPtr;
+ if (p != null)
+ {
+ unsafe
+ {
+ byte* q = text.AsciiStringPtr;
+ if (q != null)
+ {
+ for (int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
+ if (*(p + i) != *(q + j)) return false;
+ return true;
+ }
+ }
+ string textSource = text.Source;
+ if (textSource != null)
+ {
+ for (int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
+ if (((char)*(p + i)) != textSource[j]) return false;
+ return true;
+ }
+ ISourceText textProvider = text.TextProvider;
+ if (textProvider == null) { Debug.Assert(false); return false; }
+ for (int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
+ if (((char)*(p + i)) != textProvider[j]) return false;
+ return true;
+ }
+ }
+ string source = this.Source;
+ if (source != null)
+ {
+ unsafe
+ {
+ byte* q = text.AsciiStringPtr;
+ if (q != null)
+ {
+ for (int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
+ if (source[i] != (char)*(q + j)) return false;
+ return true;
+ }
+ }
+ string textSource = text.Source;
+ if (textSource != null)
+ {
+ for (int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
+ if (source[i] != textSource[j]) return false;
+ return true;
+ }
+ ISourceText textProvider = text.TextProvider;
+ if (textProvider == null) { Debug.Assert(false); return false; }
+ for (int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
+ if (source[i] != textProvider[j]) return false;
+ return true;
+ }
+ {
+ ISourceText myProvider = this.TextProvider;
+ if (myProvider == null) { Debug.Assert(false); return false; }
+ unsafe
+ {
+ byte* q = text.AsciiStringPtr;
+ if (q != null)
+ {
+ for (int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
+ if (myProvider[i] != (char)*(q + j)) return false;
+ return true;
+ }
+ }
+ string textSource = text.Source;
+ if (textSource != null)
+ {
+ for (int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
+ if (myProvider[i] != textSource[j]) return false;
+ return true;
+ }
+ ISourceText textProvider = text.TextProvider;
+ if (textProvider == null) { Debug.Assert(false); return false; }
+ for (int i = offset, j = textOffset, n = offset + length; i < n; i++, j++)
+ if (myProvider[i] != textProvider[j]) return false;
+ return true;
+ }
+ }
+ /// <summary>
+ /// Retrieves a substring from this instance. The substring starts at a specified character position and has a specified length.
+ /// </summary>
+ public string/*!*/ Substring(int position, int length)
+ {
+ if (position < 0 || length < 0 || position + length > this.Length + 1) { Debug.Assert(false); return ""; }
+ if (position + length > this.Length) length = this.Length - position; //Allow virtual EOF character to be included in length
+ if (this.AsciiStringPtr != null)
+ {
+ unsafe
+ {
+ return new String((sbyte*)this.AsciiStringPtr, position, length, System.Text.Encoding.ASCII);
+ }
+ }
+ else if (this.Source != null)
+ return this.Source.Substring(position, length);
+ else if (this.TextProvider != null)
+ return this.TextProvider.Substring(position, length);
+ else
+ {
+ Debug.Assert(false);
+ return "";
+ }
+ }
+ /// <summary>
+ /// Retrieves the character at the given position. The first character is at position zero.
+ /// </summary>
+ public char this[int position]
+ {
+ get
+ {
+ if (position < 0 || position >= this.Length) { Debug.Assert(false); return (char)0; }
+ if (this.AsciiStringPtr != null)
+ {
+ unsafe
+ {
+ unchecked
+ {
+ return (char)*(this.AsciiStringPtr + position);
+ }
+ }
+ }
+ else if (this.Source != null)
+ return this.Source[position];
+ else if (this.TextProvider != null)
+ return this.TextProvider[position];
+ else
+ {
+ Debug.Assert(false);
+ return (char)0;
+ }
+ }
+ }
+ }
+ /// <summary>
+ /// A source document from which an Abstract Syntax Tree has been derived.
+ /// </summary>
+ public class Document
+ {
+ /// <summary>
+ /// A Guid that identifies the kind of document to applications such as a debugger. Typically System.Diagnostics.SymbolStore.SymDocumentType.Text.
+ /// </summary>
+ public System.Guid DocumentType;
+ /// <summary>
+ /// A Guid that identifies the programming language used in the source document. Typically used by a debugger to locate language specific logic.
+ /// </summary>
+ public System.Guid Language;
+ /// <summary>
+ /// A Guid that identifies the compiler vendor programming language used in the source document. Typically used by a debugger to locate vendor specific logic.
+ /// </summary>
+ public System.Guid LanguageVendor;
+ /// <summary>
+ /// The line number corresponding to the first character in Text. Typically 1 but can be changed by C# preprocessor directives.
+ /// </summary>
+ public int LineNumber;
+ /// <summary>
+ /// Indicates that the document contains machine generated source code that should not show up in tools such as debuggers.
+ /// Can be set by C# preprocessor directives.
+ /// </summary>
+ public bool Hidden;
+ /// <summary>
+ /// 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.
+ /// </summary>
+ public string/*!*/ Name;
+ /// <summary>
+ /// Contains the source text.
+ /// </summary>
+ public DocumentText Text;
+ public Document()
+ {
+ this.Name = "";
+ //^ base();
+ }
+ public Document(string/*!*/ name, int lineNumber, string text, System.Guid documentType, System.Guid language, System.Guid languageVendor)
+ : this(name, lineNumber, new DocumentText(text), documentType, language, languageVendor)
+ {
+ }
+ public Document(string/*!*/ name, int lineNumber, DocumentText text, System.Guid documentType, System.Guid language, System.Guid languageVendor)
+ {
+ this.DocumentType = documentType;
+ this.Language = language;
+ this.LanguageVendor = languageVendor;
+ this.LineNumber = lineNumber;
+ this.Name = name;
+ this.Text = text;
+ //^ base();
+ }
+
+ /// <summary>
+ /// Maps the given zero based character position to the number of the source line containing the same character.
+ /// Line number counting starts from the value of LineNumber.
+ /// </summary>
+ public virtual int GetLine(int position)
+ {
+ int line = 0; int column = 0;
+ this.GetPosition(position, out line, out column);
+ return line + this.LineNumber;
+ }
+ /// <summary>
+ /// Maps the given zero based character position in the entire text to the position of the same character in a source line.
+ /// Counting within the source line starts at 1.
+ /// </summary>
+ public virtual int GetColumn(int position)
+ {
+ int line = 0; int column = 0;
+ this.GetPosition(position, out line, out column);
+ return column + 1;
+ }
+
+ /// <summary>
+ /// Given a startLine, startColum, endLine and endColumn, this returns the corresponding startPos and endPos. In other words it
+ /// converts a range expression in line and columns to a range expressed as a start and end character position.
+ /// </summary>
+ /// <param name="startLine">The number of the line containing the first character. The number of the first line equals this.LineNumber.</param>
+ /// <param name="startColumn">The position of the first character relative to the start of the line. Counting from 1.</param>
+ /// <param name="endLine">The number of the line contain the character that immediate follows the last character of the range.</param>
+ /// <param name="endColumn">The position, in the last line, of the character that immediately follows the last character of the range.</param>
+ /// <param name="startPos">The position in the entire text of the first character of the range, counting from 0.</param>
+ /// <param name="endPos">The position in the entire text of the character following the last character of the range.</param>
+ public virtual void GetOffsets(int startLine, int startColumn, int endLine, int endColumn, out int startPos, out int endPos)
+ {
+ lock (this)
+ {
+ if (this.lineOffsets == null) this.ComputeLineOffsets();
+ //^ assert this.lineOffsets != null;
+ startPos = this.lineOffsets[startLine - this.LineNumber] + startColumn - 1;
+ endPos = this.lineOffsets[endLine - this.LineNumber] + endColumn - 1;
+ }
+ }
+
+ /// <summary>
+ /// Retrieves a substring from the text of this Document. The substring starts at a specified character position and has a specified length.
+ /// </summary>
+ public virtual string Substring(int position, int length)
+ {
+ if (this.Text == null) return null;
+ return this.Text.Substring(position, length);
+ }
+
+ /// <summary>
+ /// Counts the number of end of line marker sequences in the given text.
+ /// </summary>
+ protected int GetLineCount(string/*!*/ text)
+ {
+ int n = text == null ? 0 : text.Length;
+ int count = 0;
+ for (int i = 0; i < n; i++)
+ {
+ switch (text[i])
+ {
+ case '\r':
+ if (i + 1 < n && text[i + 1] == '\n')
+ i++;
+ count++;
+ break;
+ case '\n':
+ case (char)0x2028:
+ case (char)0x2029:
+ count++;
+ break;
+ }
+ }
+ return count;
+ }
+ /// <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>
+ private int[] lineOffsets;
+ /// <summary>The number of lines in Text.</summary>
+ private int lines;
+
+ /// <summary>
+ /// Returns the index in this.lineOffsets array such that this.lineOffsets[index] is less than or equal to offset
+ /// and offset is less than lineOffsets[index+1]
+ /// </summary>
+ private int Search(int offset)
+ {
+ tryAgain:
+ int[] lineOffsets = this.lineOffsets;
+ int lines = this.lines;
+ if (lineOffsets == null) { Debug.Assert(false); return -1; }
+ if (offset < 0) { Debug.Assert(false); return -1; }
+ int mid = 0;
+ int low = 0;
+ int high = lines - 1;
+ while (low < high)
+ {
+ mid = (low + high) / 2;
+ if (lineOffsets[mid] <= offset)
+ {
+ if (offset < lineOffsets[mid + 1])
+ return mid;
+ else
+ low = mid + 1;
+ }
+ else
+ high = mid;
+ }
+ Debug.Assert(lines == this.lines);
+ Debug.Assert(lineOffsets[low] <= offset);
+ Debug.Assert(offset < lineOffsets[low + 1]);
+ if (lineOffsets != this.lineOffsets) goto tryAgain;
+ return low;
+ }
+
+ /// <summary>
+ /// Maps the given zero based character position in the entire text to a (line, column) pair corresponding to the same position.
+ /// Counting within the source line starts at 0. Counting source lines start at 0.
+ /// </summary>
+ private void GetPosition(int offset, out int line, out int column)
+ {
+ line = 0; column = 0;
+ if (offset < 0 || this.Text == null || offset > this.Text.Length) { Debug.Assert(false); return; }
+ lock (this)
+ {
+ if (this.lineOffsets == null) this.ComputeLineOffsets();
+ if (this.lineOffsets == null) { Debug.Assert(false); return; }
+ int[] lineOffsets = this.lineOffsets;
+ int index = this.Search(offset);
+ Debug.Assert(lineOffsets == this.lineOffsets);
+ if (index < 0 || index >= this.lineOffsets.Length) { Debug.Assert(false); return; }
+ Debug.Assert(this.lineOffsets[index] <= offset && offset < this.lineOffsets[index + 1]);
+ line = index;
+ column = offset - this.lineOffsets[index];
+ }
+ }
+ /// <summary>
+ /// Adds the given offset to the this.lineOffsets table as the offset corresponding to the start of line this.lines+1.
+ /// </summary>
+ private void AddOffset(int offset)
+ {
+ if (this.lineOffsets == null || this.lines < 0) { Debug.Assert(false); return; }
+ if (this.lines >= this.lineOffsets.Length)
+ {
+ int n = this.lineOffsets.Length;
+ if (n <= 0) n = 16;
+ int[] newLineOffsets = new int[n * 2];
+ Array.Copy(this.lineOffsets, newLineOffsets, this.lineOffsets.Length);
+ this.lineOffsets = newLineOffsets;
+ }
+ this.lineOffsets[this.lines++] = offset;
+ }
+ public virtual void InsertOrDeleteLines(int offset, int lineCount)
+ {
+ if (lineCount == 0) return;
+ if (offset < 0 || this.Text == null || offset > this.Text.Length) { Debug.Assert(false); return; }
+ lock (this)
+ {
+ if (this.lineOffsets == null)
+ if (this.lineOffsets == null) this.ComputeLineOffsets();
+ if (lineCount < 0)
+ this.DeleteLines(offset, -lineCount);
+ else
+ this.InsertLines(offset, lineCount);
+ }
+ }
+ private void DeleteLines(int offset, int lineCount)
+ //^ requires offset >= 0 && this.Text != null && offset < this.Text.Length && lineCount > 0 && this.lineOffsets != null;
+ {
+ Debug.Assert(offset >= 0 && this.Text != null && offset < this.Text.Length && lineCount > 0 && this.lineOffsets != null);
+ int index = this.Search(offset);
+ if (index < 0 || index >= this.lines) { Debug.Assert(false); return; }
+ for (int i = index + 1; i + lineCount < this.lines; i++)
+ {
+ this.lineOffsets[i] = this.lineOffsets[i + lineCount];
+ }
+ this.lines -= lineCount;
+ if (this.lines <= index) { Debug.Assert(false); this.lines = index + 1; }
+ }
+ private void InsertLines(int offset, int lineCount)
+ //^ requires offset >= 0 && this.Text != null && offset < this.Text.Length && lineCount > 0 && this.lineOffsets != null;
+ {
+ Debug.Assert(offset >= 0 && this.Text != null && offset < this.Text.Length && lineCount > 0 && this.lineOffsets != null);
+ int index = this.Search(offset);
+ if (index < 0 || index >= this.lines) { Debug.Assert(false); return; }
+ int n = this.lineOffsets[this.lines - 1];
+ for (int i = 0; i < lineCount; i++) this.AddOffset(++n);
+ for (int i = lineCount; i > 0; i--)
+ {
+ this.lineOffsets[index + i + 1] = this.lineOffsets[index + 1];
+ }
+ }
+ /// <summary>
+ /// Populates this.lineOffsets with 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>
+ private void ComputeLineOffsets()
+ //ensures this.lineOffsets != null;
+ {
+ if (this.Text == null) { Debug.Assert(false); return; }
+ int n = this.Text.Length;
+ this.lineOffsets = new int[n / 10 + 1];
+ this.lines = 0;
+ this.AddOffset(0);
+ for (int i = 0; i < n; i++)
+ {
+ switch (this.Text[i])
+ {
+ case '\r':
+ if (i + 1 < n && this.Text[i + 1] == '\n')
+ i++;
+ this.AddOffset(i + 1);
+ break;
+ case '\n':
+ case (char)0x2028:
+ case (char)0x2029:
+ this.AddOffset(i + 1);
+ break;
+ }
+ }
+ this.AddOffset(n + 1);
+ this.AddOffset(n + 2);
+ }
+
+ /// <summary> Add one to this every time a Document instance gets a unique key.</summary>
+ private static int uniqueKeyCounter;
+ private int uniqueKey;
+ /// <summary>
+ /// An integer that uniquely distinguishes this document instance from every other document instance.
+ /// This provides an efficient equality test to facilitate hashing.
+ /// </summary>
+ public int UniqueKey
+ {
+ get
+ {
+ if (this.uniqueKey == 0)
+ {
+ TryAgain:
+ int c = Document.uniqueKeyCounter;
+ int cp1 = c == int.MaxValue ? 1 : c + 1;
+ if (System.Threading.Interlocked.CompareExchange(ref Document.uniqueKeyCounter, cp1, c) != c) goto TryAgain;
+ this.uniqueKey = cp1;
+ }
+ return this.uniqueKey;
+ }
+ }
+ }
+#endif
+#if !MinimalReader
+ /// <summary>
+ /// For creating source contexts that have just a filename, start line and column and end line and column.
+ /// If a SourceContext has a DocumentWithPrecomputedLineNumbers as its Document, then it should have 0 as its StartPos
+ /// and 1 as its EndPos because those are used here to decide what to return.
+ /// </summary>
+ public class DocumentWithPrecomputedLineNumbers : Document
+ {
+ private int startLine, startCol, endLine, endCol;
+ public DocumentWithPrecomputedLineNumbers(string/*!*/ filename, int startLine, int startCol, int endLine, int endCol)
+ {
+ this.Name = filename;
+ this.startLine = startLine;
+ this.startCol = startCol;
+ this.endLine = endLine;
+ this.endCol = endCol;
+ }
+ public override int GetColumn(int offset) { return offset == 0 ? this.startCol : this.endCol; }
+ public override int GetLine(int offset) { return offset == 0 ? this.startLine : this.endLine; }
+ }
+#endif
+#if UseSingularityPDB
+ internal class PdbDocument : Document {
+ internal PdbDocument(PdbLines lines) {
+ this.Name = lines.file.name;
+ this.lines = lines;
+ }
+ PdbLines lines;
+ public override int GetColumn(int position) {
+ PdbLine line = this.lines.lines[position/2];
+ if (position%2 == 0)
+ return line.colBegin;
+ else
+ return line.colEnd;
+ }
+ public override int GetLine(int position) {
+ PdbLine line = this.lines.lines[position/2];
+ return (int)line.line;
+ }
+ }
+#elif !ROTOR
+ internal class UnmanagedDocument : Document
+ {
+ internal UnmanagedDocument(IntPtr ptrToISymUnmanagedDocument)
+ {
+ //^ base();
+ ISymUnmanagedDocument idoc =
+ (ISymUnmanagedDocument)System.Runtime.InteropServices.Marshal.GetTypedObjectForIUnknown(ptrToISymUnmanagedDocument, typeof(ISymUnmanagedDocument));
+ if (idoc != null)
+ {
+ try
+ {
+#if !FxCop
+ idoc.GetDocumentType(out this.DocumentType);
+ idoc.GetLanguage(out this.Language);
+ idoc.GetLanguageVendor(out this.LanguageVendor);
+#endif
+ uint capacity = 1024;
+ uint len = 0;
+ char[] buffer = new char[capacity];
+ while (capacity >= 1024)
+ {
+ idoc.GetURL(capacity, out len, buffer);
+ if (len < capacity) break;
+ capacity += 1024;
+ buffer = new char[capacity];
+ }
+ if (len > 0)
+ this.Name = new String(buffer, 0, (int)len - 1);
+ }
+ finally
+ {
+ System.Runtime.InteropServices.Marshal.ReleaseComObject(idoc);
+ }
+ }
+#if !FxCop
+ this.LineNumber = -1;
+ this.Text = null;
+#endif
+ }
+
+ private Int32List/*!*/ lineList = new Int32List();
+ private Int32List/*!*/ columnList = new Int32List();
+#if !FxCop
+ public override int GetLine(int offset)
+ {
+ return this.lineList[offset];
+ }
+ public override int GetColumn(int offset)
+ {
+ return this.columnList[offset];
+ }
+ public override void GetOffsets(int startLine, int startColumn, int endLine, int endColumn, out int startCol, out int endCol)
+ {
+ int i = UnmanagedDocument.BinarySearch(this.lineList, startLine);
+ Int32List columnList = this.columnList;
+ startCol = 0;
+ for (int j = i, n = columnList.Count; j < n; j++)
+ {
+ if (columnList[j] >= startColumn) { startCol = j; break; }
+ }
+ endCol = 0;
+ i = UnmanagedDocument.BinarySearch(this.lineList, endLine);
+ for (int j = i, n = columnList.Count; j < n; j++)
+ {
+ if (columnList[j] >= endColumn) { endCol = j; break; }
+ }
+ }
+ private static int BinarySearch(Int32List/*!*/ list, int value)
+ {
+ int mid = 0;
+ int low = 0;
+ int high = list.Count - 1;
+ while (low < high)
+ {
+ mid = low + (high - low) / 2;
+ if (list[mid] <= value)
+ {
+ if (list[mid + 1] > value)
+ return mid;
+ else
+ low = mid + 1;
+ }
+ else
+ high = mid;
+ }
+ return low;
+ }
+ public override void InsertOrDeleteLines(int offset, int lineCount)
+ {
+ Debug.Assert(false); //Caller should not be modifying an umanaged document
+ }
+#endif
+ internal int GetOffset(uint line, uint column)
+ {
+ this.lineList.Add((int)line);
+ this.columnList.Add((int)column);
+ return this.lineList.Count - 1;
+ }
+ }
+#endif // !ROTOR
+#if FxCop
+ class Document{
+ internal string Name;
+ }
+ public struct SourceContext{
+ private string name;
+ private int startLine;
+ private int endLine;
+ private int startColumn;
+ private int endColumn;
+ internal SourceContext(string name, uint startLine, uint endLine, uint startColumn, uint endColumn){
+ this.name = name;
+ checked {
+ this.startLine = (int)startLine;
+ this.endLine = (int)endLine;
+ this.startColumn = (int)startColumn;
+ this.endColumn = (int)endColumn;
+ }
+ }
+ public string FileName{
+ get{return this.name;}
+ }
+ public int StartLine{
+ get{return this.startLine;}
+ }
+ public int EndLine{
+ get{return this.endLine;}
+ }
+ public int StartColumn{
+ get{return this.startColumn;}
+ }
+ public int EndColumn{
+ get{return this.endColumn;}
+ }
+ }
+#else
+ /// <summary>
+ /// Records a location within a source document that corresponds to an Abstract Syntax Tree node.
+ /// </summary>
+ public struct SourceContext
+ {
+ /// <summary>The source document within which the AST node is located. Null if the node is not derived from a source document.</summary>
+ public Document Document;
+ /// <summary>
+ /// The zero based index of the first character beyond the last character in the source document that corresponds to the AST node.
+ /// </summary>
+ public int EndPos;
+ /// <summary>
+ /// The zero based index of the first character in the source document that corresponds to the AST node.
+ /// </summary>
+ public int StartPos;
+ public SourceContext(Document document)
+ : this(document, 0, document == null ? 0 : (document.Text == null ? 0 : document.Text.Length))
+ {
+ }
+ public SourceContext(Document document, int startPos, int endPos)
+ {
+ this.Document = document;
+ this.StartPos = startPos;
+ this.EndPos = endPos;
+ }
+ public SourceContext(Document/*!*/ document,
+ int startLine, int startColumn, int endLine, int endColumn)
+ {
+ this.Document = document;
+ this.Document.GetOffsets(startLine, startColumn, endLine, endColumn, out this.StartPos, out this.EndPos);
+ }
+ /// <summary>
+ /// The number (counting from Document.LineNumber) of the line containing the first character in the source document that corresponds to the AST node.
+ /// </summary>
+ public int StartLine
+ {
+ get
+ {
+ if (this.Document == null) return 0;
+ return this.Document.GetLine(this.StartPos);
+ }
+ }
+ /// <summary>
+ /// The number (counting from one) of the line column containing the first character in the source document that corresponds to the AST node.
+ /// </summary>
+ public int StartColumn
+ {
+ get
+ {
+ if (this.Document == null) return 0;
+ return this.Document.GetColumn(this.StartPos);
+ }
+ }
+ /// <summary>
+ /// 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.
+ /// </summary>
+ public int EndLine
+ {
+ get
+ {
+#if UseSingularityPDB
+ if (this.Document == null || (this.Document.Text == null && !(this.Document is PdbDocument))) return 0;
+#elif !ROTOR
+ if (this.Document == null || (this.Document.Text == null && !(this.Document is UnmanagedDocument))) return 0;
+#else
+ if (this.Document == null || this.Document.Text == null) return 0;
+#endif
+ if (this.Document.Text != null && this.EndPos >= this.Document.Text.Length) this.EndPos = this.Document.Text.Length;
+ return this.Document.GetLine(this.EndPos);
+ }
+ }
+ /// <summary>
+ /// 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.
+ /// </summary>
+ public int EndColumn
+ {
+ get
+ {
+#if UseSingularityPDB
+ if (this.Document == null || (this.Document.Text == null && !(this.Document is PdbDocument))) return 0;
+#elif !ROTOR
+ if (this.Document == null || (this.Document.Text == null && !(this.Document is UnmanagedDocument))) return 0;
+#else
+ if (this.Document == null || this.Document.Text == null) return 0;
+#endif
+ if (this.Document.Text != null && this.EndPos >= this.Document.Text.Length) this.EndPos = this.Document.Text.Length;
+ return this.Document.GetColumn(this.EndPos);
+ }
+ }
+ /// <summary>
+ /// Returns true if the line and column is greater than or equal the position of the first character
+ /// and less than or equal to the position of the last character
+ /// of the source document that corresponds to the AST node.
+ /// </summary>
+ /// <param name="line">A line number(counting from Document.LineNumber)</param>
+ /// <param name="column">A column number (counting from one)</param>
+ /// <returns></returns>
+ public bool Encloses(int line, int column)
+ {
+ if (line < this.StartLine || line > this.EndLine) return false;
+ if (line == this.StartLine) return column >= this.StartColumn && (column <= this.EndColumn || line < this.EndLine);
+ if (line == this.EndLine) return column <= this.EndColumn;
+ return true;
+ }
+ public bool Encloses(SourceContext sourceContext)
+ {
+ return this.StartPos <= sourceContext.StartPos && this.EndPos >= sourceContext.EndPos && this.EndPos > sourceContext.StartPos;
+ }
+ /// <summary>
+ /// The substring of the source document that corresponds to the AST node.
+ /// </summary>
+ public string SourceText
+ {
+ get
+ {
+ if (this.Document == null) return null;
+ return this.Document.Substring(this.StartPos, this.EndPos - this.StartPos);
+ }
+ }
+ }
+#endif
+#if !MinimalReader
+ public struct SourceChange
+ {
+ public SourceContext SourceContext;
+ public string ChangedText;
+ }
+ /// <summary>
+ /// Allows a compilation to output progress messages and to query if cancellation was requested.
+ /// </summary>
+ public class CompilerSite
+ {
+ public virtual void OutputMessage(string message)
+ {
+ }
+ public virtual bool ShouldCancel
+ {
+ get
+ {
+ return false;
+ }
+ }
+ }
+#endif
+#if !NoWriter
+ public enum PlatformType { notSpecified, v1, v11, v2, cli1 }
+ public class CompilerOptions : System.CodeDom.Compiler.CompilerParameters
+ {
+ public StringCollection AliasesForReferencedAssemblies;
+ public ModuleKindFlags ModuleKind = ModuleKindFlags.ConsoleApplication;
+ public bool EmitManifest = true;
+ public StringList DefinedPreProcessorSymbols;
+ public string XMLDocFileName;
+ public string RecursiveWildcard;
+ public StringList ReferencedModules;
+ public string Win32Icon;
+#if !WHIDBEY
+ private StringCollection embeddedResources = new StringCollection();
+ public StringCollection EmbeddedResources{
+ get{return this.embeddedResources;}
+ }
+ private StringCollection linkedResources = new StringCollection();
+ public StringCollection LinkedResources{
+ get{return this.linkedResources;}
+ }
+#endif
+#if VS7
+ private System.Security.Policy.Evidence evidence;
+ public System.Security.Policy.Evidence Evidence{
+ get{return this.evidence;}
+ set{this.evidence = value;}
+ }
+#endif
+ public bool PDBOnly;
+ public bool Optimize;
+ public bool IncrementalCompile;
+ public Int32List SuppressedWarnings;
+ public bool CheckedArithmetic;
+ public bool AllowUnsafeCode;
+ public bool DisplayCommandLineHelp;
+ public bool SuppressLogo;
+ public long BaseAddress; //TODO: default value
+ public string BugReportFileName;
+ public object CodePage; //must be an int if not null
+ public bool EncodeOutputInUTF8;
+ public bool FullyQualifyPaths;
+ public int FileAlignment;
+ public bool NoStandardLibrary;
+ public StringList AdditionalSearchPaths;
+ public bool HeuristicReferenceResolution;
+ public string RootNamespace;
+ public bool CompileAndExecute;
+ public object UserLocaleId; //must be an int if not null
+ public string StandardLibraryLocation;
+ public PlatformType TargetPlatform; //TODO: rename this to TargetRuntime
+#if !MinimalReader
+ public ProcessorType TargetProcessor;
+#endif
+ public string TargetPlatformLocation;
+ public string AssemblyKeyFile;
+ public string AssemblyKeyName;
+ public bool DelaySign;
+ public TargetInformation TargetInformation;
+ public Int32List SpecificWarningsToTreatAsErrors;
+ public Int32List SpecificWarningsNotToTreatAsErrors;
+ public string OutputPath;
+ public string ExplicitOutputExtension;
+ public AppDomain TargetAppDomain;
+ public bool MayLockFiles;
+ public string ShadowedAssembly;
+ public bool UseStandardConfigFile;
+#if !MinimalReader
+ public CompilerSite Site;
+#endif
+#if ExtendedRuntime
+ /// <summary>
+ /// True if the source code for the assembly specify only contracts.
+ /// </summary>
+ public bool IsContractAssembly;
+ /// <summary>
+ /// Do not emit run-time checks for requires clauses of non-externally-accessible methods, assert statements, loop invariants, and ensures clauses.
+ /// </summary>
+ public bool DisableInternalChecks;
+ /// <summary>
+ /// Do not emit run-time checks for assume statements.
+ /// </summary>
+ public bool DisableAssumeChecks;
+ /// <summary>
+ /// Do not emit run-time checks for requires clauses of externally accessible methods.
+ /// </summary>
+ public bool DisableDefensiveChecks;
+ /// <summary>
+ /// Disable the guarded classes feature, which integrates run-time enforcement of object invariants, ownership, and safe concurrency.
+ /// </summary>
+ public bool DisableGuardedClassesChecks;
+ public bool DisableInternalContractsMetadata;
+ public bool DisablePublicContractsMetadata;
+ /// <summary>
+ /// Disable the runtime test against null on non-null typed parameters on public methods
+ /// </summary>
+ public bool DisableNullParameterValidation;
+ public virtual bool LoadDebugSymbolsForReferencedAssemblies {
+ get { return false; }
+ }
+
+ /// <summary>
+ /// If set, the compiler will only parse and then emit an xml file with detailed source contexts
+ /// about what is parsed.
+ /// </summary>
+ public bool EmitSourceContextsOnly = false;
+
+#endif
+ public CompilerOptions()
+ {
+ }
+ public CompilerOptions(CompilerOptions source)
+ {
+ if (source == null) { Debug.Assert(false); return; }
+ this.AdditionalSearchPaths = source.AdditionalSearchPaths; //REVIEW: clone the list?
+ this.AliasesForReferencedAssemblies = source.AliasesForReferencedAssemblies;
+ this.AllowUnsafeCode = source.AllowUnsafeCode;
+ this.AssemblyKeyFile = source.AssemblyKeyFile;
+ this.AssemblyKeyName = source.AssemblyKeyName;
+ this.BaseAddress = source.BaseAddress;
+ this.BugReportFileName = source.BugReportFileName;
+ this.CheckedArithmetic = source.CheckedArithmetic;
+ this.CodePage = source.CodePage;
+ this.CompileAndExecute = source.CompileAndExecute;
+ this.CompilerOptions = source.CompilerOptions;
+ this.DefinedPreProcessorSymbols = source.DefinedPreProcessorSymbols;
+ this.DelaySign = source.DelaySign;
+#if ExtendedRuntime
+ this.DisableAssumeChecks = source.DisableAssumeChecks;
+ this.DisableDefensiveChecks = source.DisableDefensiveChecks;
+ this.DisableGuardedClassesChecks = source.DisableGuardedClassesChecks;
+ this.DisableInternalChecks = source.DisableInternalChecks;
+ this.DisableInternalContractsMetadata = source.DisableInternalContractsMetadata;
+ this.DisablePublicContractsMetadata = source.DisablePublicContractsMetadata;
+#endif
+ this.DisplayCommandLineHelp = source.DisplayCommandLineHelp;
+ if (source.EmbeddedResources != null)
+ foreach (string s in source.EmbeddedResources) this.EmbeddedResources.Add(s);
+ this.EmitManifest = source.EmitManifest;
+ this.EncodeOutputInUTF8 = source.EncodeOutputInUTF8;
+ this.Evidence = source.Evidence;
+ this.ExplicitOutputExtension = source.ExplicitOutputExtension;
+ this.FileAlignment = source.FileAlignment;
+ this.FullyQualifyPaths = source.FullyQualifyPaths;
+ this.GenerateExecutable = source.GenerateExecutable;
+ this.GenerateInMemory = source.GenerateInMemory;
+ this.HeuristicReferenceResolution = source.HeuristicReferenceResolution;
+ this.IncludeDebugInformation = source.IncludeDebugInformation;
+ this.IncrementalCompile = source.IncrementalCompile;
+#if ExtendedRuntime
+ this.IsContractAssembly = source.IsContractAssembly;
+#endif
+ if (source.LinkedResources != null)
+ foreach (string s in source.LinkedResources) this.LinkedResources.Add(s);
+ this.MainClass = source.MainClass;
+ this.MayLockFiles = source.MayLockFiles;
+ this.ModuleKind = source.ModuleKind;
+ this.NoStandardLibrary = source.NoStandardLibrary;
+ this.Optimize = source.Optimize;
+ this.OutputAssembly = source.OutputAssembly;
+ this.OutputPath = source.OutputPath;
+ this.PDBOnly = source.PDBOnly;
+ this.RecursiveWildcard = source.RecursiveWildcard;
+ if (source.ReferencedAssemblies != null)
+ foreach (string s in source.ReferencedAssemblies) this.ReferencedAssemblies.Add(s);
+ this.ReferencedModules = source.ReferencedModules;
+ this.RootNamespace = source.RootNamespace;
+ this.ShadowedAssembly = source.ShadowedAssembly;
+ this.SpecificWarningsToTreatAsErrors = source.SpecificWarningsToTreatAsErrors;
+ this.StandardLibraryLocation = source.StandardLibraryLocation;
+ this.SuppressLogo = source.SuppressLogo;
+ this.SuppressedWarnings = source.SuppressedWarnings;
+ this.TargetAppDomain = source.TargetAppDomain;
+ this.TargetInformation = source.TargetInformation;
+ this.TargetPlatform = source.TargetPlatform;
+ this.TargetPlatformLocation = source.TargetPlatformLocation;
+ this.TreatWarningsAsErrors = source.TreatWarningsAsErrors;
+ this.UserLocaleId = source.UserLocaleId;
+ this.UserToken = source.UserToken;
+ this.WarningLevel = source.WarningLevel;
+ this.Win32Icon = source.Win32Icon;
+ this.Win32Resource = source.Win32Resource;
+ this.XMLDocFileName = source.XMLDocFileName;
+ }
+ public virtual string GetOptionHelp()
+ {
+ return null;
+ }
+ public virtual CompilerOptions Clone()
+ {
+ return (CompilerOptions)this.MemberwiseClone();
+ }
+ }
+#endif
+ public sealed class MarshallingInformation
+ {
+ private string @class;
+ private string cookie;
+ private int elementSize;
+ private NativeType elementType;
+ private NativeType nativeType;
+ private int numberOfElements;
+ private int paramIndex;
+ private int size;
+ public MarshallingInformation Clone()
+ {
+ return (MarshallingInformation)base.MemberwiseClone();
+ }
+ public string Class
+ {
+ get { return this.@class; }
+ set { this.@class = value; }
+ }
+ public string Cookie
+ {
+ get { return this.cookie; }
+ set { this.cookie = value; }
+ }
+ public int ElementSize
+ {
+ get { return this.elementSize; }
+ set { this.elementSize = value; }
+ }
+ public NativeType ElementType
+ {
+ get { return this.elementType; }
+ set { this.elementType = value; }
+ }
+ public NativeType NativeType
+ {
+ get { return this.nativeType; }
+ set { this.nativeType = value; }
+ }
+ public int NumberOfElements
+ {
+ get { return this.numberOfElements; }
+ set { this.numberOfElements = value; }
+ }
+ public int ParamIndex
+ {
+ get { return this.paramIndex; }
+ set { this.paramIndex = value; }
+ }
+ public int Size
+ {
+ get { return this.size; }
+ set { this.size = value; }
+ }
+ }
+#if !NoWriter
+ public struct TargetInformation
+ {
+ public string Company;
+ public string Configuration;
+ public string Copyright;
+ public string Culture;
+ public string Description;
+ public string Product;
+ public string ProductVersion;
+ public string Title;
+ public string Trademark;
+ public string Version;
+ }
+#endif
+ public enum NativeType
+ {
+ Bool = 0x2, // 4 byte boolean value (true != 0, false == 0)
+ I1 = 0x3, // 1 byte signed value
+ U1 = 0x4, // 1 byte unsigned value
+ I2 = 0x5, // 2 byte signed value
+ U2 = 0x6, // 2 byte unsigned value
+ I4 = 0x7, // 4 byte signed value
+ U4 = 0x8, // 4 byte unsigned value
+ I8 = 0x9, // 8 byte signed value
+ U8 = 0xa, // 8 byte unsigned value
+ R4 = 0xb, // 4 byte floating point
+ R8 = 0xc, // 8 byte floating point
+ Currency = 0xf, // A currency
+ BStr = 0x13, // OLE Unicode BSTR
+ LPStr = 0x14, // Ptr to SBCS string
+ LPWStr = 0x15, // Ptr to Unicode string
+ LPTStr = 0x16, // Ptr to OS preferred (SBCS/Unicode) string
+ ByValTStr = 0x17, // OS preferred (SBCS/Unicode) inline string (only valid in structs)
+ IUnknown = 0x19, // COM IUnknown pointer.
+ IDispatch = 0x1a, // COM IDispatch pointer
+ Struct = 0x1b, // Structure
+ Interface = 0x1c, // COM interface
+ SafeArray = 0x1d, // OLE SafeArray
+ ByValArray = 0x1e, // Array of fixed size (only valid in structs)
+ SysInt = 0x1f, // Hardware natural sized signed integer
+ SysUInt = 0x20,
+ VBByRefStr = 0x22,
+ AnsiBStr = 0x23, // OLE BSTR containing SBCS characters
+ TBStr = 0x24, // Ptr to OS preferred (SBCS/Unicode) BSTR
+ VariantBool = 0x25, // OLE defined BOOLEAN (2 bytes, true == -1, false == 0)
+ FunctionPtr = 0x26, // Function pointer
+ AsAny = 0x28, // Paired with Object type and does runtime marshalling determination
+ LPArray = 0x2a, // C style array
+ LPStruct = 0x2b, // Pointer to a structure
+ CustomMarshaler = 0x2c, // Native type supplied by custom code
+ Error = 0x2d,
+ NotSpecified = 0x50,
+ }
+ ///0-: Common
+ ///1000-: HScript
+ ///2000-: EcmaScript
+ ///3000-: Zonnon
+ ///4000-: Comega
+ ///5000-: X++
+ ///6000-: Spec#
+ ///7000-: Sing#
+ ///8000-: Xaml
+ ///9000-: C/AL
+ ///For your range contact hermanv@microsoft.com
+ public enum NodeType
+ {
+ //Dummy
+ Undefined = 0,
+
+ //IL instruction node tags
+ Add,
+ Add_Ovf,
+ Add_Ovf_Un,
+ And,
+ Arglist,
+ Box,
+ Branch,
+ Call,
+ Calli,
+ Callvirt,
+ Castclass,
+ Ceq,
+ Cgt,
+ Cgt_Un,
+ Ckfinite,
+ Clt,
+ Clt_Un,
+ Conv_I,
+ Conv_I1,
+ Conv_I2,
+ Conv_I4,
+ Conv_I8,
+ Conv_Ovf_I,
+ Conv_Ovf_I_Un,
+ Conv_Ovf_I1,
+ Conv_Ovf_I1_Un,
+ Conv_Ovf_I2,
+ Conv_Ovf_I2_Un,
+ Conv_Ovf_I4,
+ Conv_Ovf_I4_Un,
+ Conv_Ovf_I8,
+ Conv_Ovf_I8_Un,
+ Conv_Ovf_U,
+ Conv_Ovf_U_Un,
+ Conv_Ovf_U1,
+ Conv_Ovf_U1_Un,
+ Conv_Ovf_U2,
+ Conv_Ovf_U2_Un,
+ Conv_Ovf_U4,
+ Conv_Ovf_U4_Un,
+ Conv_Ovf_U8,
+ Conv_Ovf_U8_Un,
+ Conv_R_Un,
+ Conv_R4,
+ Conv_R8,
+ Conv_U,
+ Conv_U1,
+ Conv_U2,
+ Conv_U4,
+ Conv_U8,
+ Cpblk,
+ DebugBreak,
+ Div,
+ Div_Un,
+ Dup,
+ EndFilter,
+ EndFinally,
+ ExceptionHandler,
+ Initblk,
+ Isinst,
+ Jmp,
+ Ldftn,
+ Ldlen,
+ Ldtoken,
+ Ldvirtftn,
+ Localloc,
+ Mkrefany,
+ Mul,
+ Mul_Ovf,
+ Mul_Ovf_Un,
+ Neg,
+ Nop,
+ Not,
+ Or,
+ Pop,
+ ReadOnlyAddressOf,
+ Refanytype,
+ Refanyval,
+ Rem,
+ Rem_Un,
+ Rethrow,
+ Shl,
+ Shr,
+ Shr_Un,
+ Sizeof,
+ SkipCheck,
+ Sub,
+ Sub_Ovf,
+ Sub_Ovf_Un,
+ SwitchInstruction,
+ Throw,
+ Unbox,
+ UnboxAny,
+ Xor,
+
+ //AST tags that are relevant to the binary reader
+ AddressDereference,
+ AddressOf,
+ AssignmentStatement,
+ Block,
+ Catch,
+ Construct,
+ ConstructArray,
+ Eq,
+ ExpressionStatement,
+ FaultHandler,
+ Filter,
+ Finally,
+ Ge,
+ Gt,
+ Identifier,
+ Indexer,
+ Instruction,
+ InterfaceExpression,
+ Le,
+ Literal,
+ LogicalNot,
+ Lt,
+ MemberBinding,
+ NamedArgument,
+ Namespace,
+ Ne,
+ Return,
+ This,
+ Try,
+
+ //Metadata node tags
+ ArrayType,
+ @Assembly,
+ AssemblyReference,
+ Attribute,
+ Class,
+ ClassParameter,
+ DelegateNode,
+ EnumNode,
+ Event,
+ Field,
+ FunctionPointer,
+ InstanceInitializer,
+ Interface,
+ Local,
+ Method,
+ Module,
+ ModuleReference,
+ OptionalModifier,
+ Parameter,
+ Pointer,
+ Property,
+ Reference,
+ RequiredModifier,
+ SecurityAttribute,
+ StaticInitializer,
+ Struct,
+ TypeParameter,
+
+#if !MinimalReader
+ // The following NodeType definitions are not required
+ // for examining assembly metadata directly from binaries
+
+ //Serialization tags used for values that are not leaf nodes.
+ Array,
+ BlockReference,
+ CompilationParameters,
+ Document,
+ EndOfRecord,
+ Expression,
+ Guid,
+ List,
+ MarshallingInformation,
+ Member,
+ MemberReference,
+ MissingBlockReference,
+ MissingExpression,
+ MissingMemberReference,
+ String,
+ StringDictionary,
+ TypeNode,
+ Uri,
+ XmlNode,
+
+ //Source-based AST node tags
+ AddEventHandler,
+ AliasDefinition,
+ AnonymousNestedFunction,
+ ApplyToAll,
+ ArglistArgumentExpression,
+ ArglistExpression,
+ ArrayTypeExpression,
+ As,
+ Assertion,
+ AssignmentExpression,
+ Assumption,
+ Base,
+#endif
+#if FxCop
+ BlockExpression,
+ StackVariable,
+#endif
+#if !MinimalReader
+ BlockExpression,
+ BoxedTypeExpression,
+ ClassExpression,
+ CoerceTuple,
+ CollectionEnumerator,
+ Comma,
+ Compilation,
+ CompilationUnit,
+ CompilationUnitSnippet,
+ Conditional,
+ ConstructDelegate,
+ ConstructFlexArray,
+ ConstructIterator,
+ ConstructTuple,
+ Continue,
+ CopyReference,
+ CurrentClosure,
+ Decrement,
+ DefaultValue,
+ DoWhile,
+ Exit,
+ ExplicitCoercion,
+ ExpressionSnippet,
+ FieldInitializerBlock,
+ Fixed,
+ FlexArrayTypeExpression,
+ For,
+ ForEach,
+ FunctionDeclaration,
+ FunctionTypeExpression,
+ Goto,
+ GotoCase,
+ If,
+ ImplicitThis,
+ Increment,
+ InvariantTypeExpression,
+ Is,
+ LabeledStatement,
+ LocalDeclaration,
+ LocalDeclarationsStatement,
+ Lock,
+ LogicalAnd,
+ LogicalOr,
+ LRExpression,
+ MethodCall,
+ NameBinding,
+ NonEmptyStreamTypeExpression,
+ NonNullableTypeExpression,
+ NonNullTypeExpression,
+ NullableTypeExpression,
+ NullCoalesingExpression,
+ OutAddress,
+ Parentheses,
+ PointerTypeExpression,
+ PostfixExpression,
+ PrefixExpression,
+ QualifiedIdentifer,
+ RefAddress,
+ ReferenceTypeExpression,
+ RefTypeExpression,
+ RefValueExpression,
+ RemoveEventHandler,
+ Repeat,
+ ResourceUse,
+ SetterValue,
+ StackAlloc,
+ StatementSnippet,
+ StreamTypeExpression,
+ Switch,
+ SwitchCase,
+ SwitchCaseBottom,
+ TemplateInstance,
+ TupleTypeExpression,
+ TypeExpression,
+ TypeIntersectionExpression,
+ TypeMemberSnippet,
+ Typeof,
+ TypeReference,
+ Typeswitch,
+ TypeswitchCase,
+ TypeUnionExpression,
+ UnaryPlus,
+ UsedNamespace,
+ VariableDeclaration,
+ While,
+ Yield,
+
+ //Extended metadata node tags
+ ConstrainedType,
+ TupleType,
+ TypeAlias,
+ TypeIntersection,
+ TypeUnion,
+
+ //Query node tags
+ Composition,
+ QueryAggregate,
+ QueryAlias,
+ QueryAll,
+ QueryAny,
+ QueryAxis,
+ QueryCommit,
+ QueryContext,
+ QueryDelete,
+ QueryDifference,
+ QueryDistinct,
+ QueryExists,
+ QueryFilter,
+ QueryGeneratedType,
+ QueryGroupBy,
+ QueryInsert,
+ QueryIntersection,
+ QueryIterator,
+ QueryJoin,
+ QueryLimit,
+ QueryOrderBy,
+ QueryOrderItem,
+ QueryPosition,
+ QueryProject,
+ QueryQuantifiedExpression,
+ QueryRollback,
+ QuerySelect,
+ QuerySingleton,
+ QueryTransact,
+ QueryTypeFilter,
+ QueryUnion,
+ QueryUpdate,
+ QueryYielder,
+
+ //Contract node tags
+ Acquire,
+ Comprehension,
+ ComprehensionBinding,
+ Ensures,
+ EnsuresExceptional,
+ EnsuresNormal,
+ Iff,
+ Implies,
+ Invariant,
+ LogicalEqual,
+ LogicalImply,
+ Maplet,
+ MethodContract,
+ Modelfield,
+ ModelfieldContract,
+ OldExpression,
+ Range,
+ Read,
+ Requires,
+ RequiresOtherwise,
+ RequiresPlain,
+ TypeContract,
+ Write,
+
+ //Node tags for explicit modifiers in front-end
+ OptionalModifierTypeExpression,
+ RequiredModifierTypeExpression,
+
+ //Temporary node tags
+ Count,
+ Exists,
+ ExistsUnique,
+ Forall,
+ Max,
+ Min,
+ Product,
+ Sum,
+ Quantifier,
+#endif // MinimalReader
+ }
+ [Flags]
+ public enum AssemblyFlags
+ {
+ None = 0x0000,
+ PublicKey = 0x0001,
+ Library = 0x0002,
+ Platform = 0x0004,
+ NowPlatform = 0x0006,
+ SideBySideCompatible = 0x0000,
+ NonSideBySideCompatible = 0x0010,
+ NonSideBySideProcess = 0x0020,
+ NonSideBySideMachine = 0x0030,
+ CompatibilityMask = 0x00F0,
+ Retargetable = 0x0100,
+ DisableJITcompileOptimizer = 0x4000,
+ EnableJITcompileTracking = 0x8000
+ }
+ public enum AssemblyHashAlgorithm
+ {
+ None = 0x0000,
+ MD5 = 0x8003,
+ SHA1 = 0x8004
+ }
+ [Flags]
+ public enum CallingConventionFlags
+ {
+ Default = 0x0,
+ C = 0x1,
+ StandardCall = 0x2,
+ ThisCall = 0x3,
+ FastCall = 0x4,
+ VarArg = 0x5,
+ ArgumentConvention = 0x7,
+ Generic = 0x10,
+ HasThis = 0x20,
+ ExplicitThis = 0x40
+ }
+ [Flags]
+ public enum EventFlags
+ {
+ None = 0x0000,
+ SpecialName = 0x0200,
+ ReservedMask = 0x0400,
+ RTSpecialName = 0x0400,
+#if !MinimalReader
+ Extend = MethodFlags.Extend, // used for languages with type extensions, e.g. Sing#
+#endif
+ }
+ [Flags]
+ public enum FieldFlags
+ {
+ None = 0x0000,
+ FieldAccessMask = 0x0007,
+ CompilerControlled = 0x0000,
+ Private = 0x0001,
+ FamANDAssem = 0x0002,
+ Assembly = 0x0003,
+ Family = 0x0004,
+ FamORAssem = 0x0005,
+ Public = 0x0006,
+ Static = 0x0010,
+ InitOnly = 0x0020,
+ Literal = 0x0040,
+ NotSerialized = 0x0080,
+ SpecialName = 0x0200,
+ PinvokeImpl = 0x2000,
+ ReservedMask = 0x9500,
+ RTSpecialName = 0x0400,
+ HasFieldMarshal = 0x1000,
+ HasDefault = 0x8000,
+ HasFieldRVA = 0x0100,
+ }
+ [Flags]
+ public enum FileFlags
+ {
+ ContainsMetaData = 0x0000,
+ ContainsNoMetaData = 0x0001
+ }
+ [Flags]
+ public enum TypeParameterFlags
+ {
+ NonVariant = 0x0000,
+ Covariant = 0x0001,
+ Contravariant = 0x0002,
+ VarianceMask = 0x0003,
+ NoSpecialConstraint = 0x0000,
+ ReferenceTypeConstraint = 0x0004,
+ ValueTypeConstraint = 0x0008,
+ DefaultConstructorConstraint = 0x0010,
+ SpecialConstraintMask = 0x001C,
+ }
+ [Flags]
+ public enum MethodImplFlags
+ {
+ CodeTypeMask = 0x0003,
+ IL = 0x0000,
+ Native = 0x0001,
+ OPTIL = 0x0002,
+ Runtime = 0x0003,
+ ManagedMask = 0x0004,
+ Unmanaged = 0x0004,
+ Managed = 0x0000,
+ ForwardRef = 0x0010,
+ PreserveSig = 0x0080,
+ InternalCall = 0x1000,
+ Synchronized = 0x0020,
+ NoInlining = 0x0008,
+#if !MinimalReader
+ MaxMethodImplVal = 0xffff
+#endif
+ }
+ [Flags]
+ public enum MethodFlags
+ {
+ MethodAccessMask = 0x0007,
+ CompilerControlled = 0x0000,
+ Private = 0x0001,
+ FamANDAssem = 0x0002,
+ Assembly = 0x0003,
+ Family = 0x0004,
+ FamORAssem = 0x0005,
+ Public = 0x0006,
+ Static = 0x0010,
+ Final = 0x0020,
+ Virtual = 0x0040,
+ HideBySig = 0x0080,
+ VtableLayoutMask = 0x0100,
+ ReuseSlot = 0x0000,
+ NewSlot = 0x0100,
+ CheckAccessOnOverride = 0x0200,
+ Abstract = 0x0400,
+ SpecialName = 0x0800,
+ PInvokeImpl = 0x2000,
+ UnmanagedExport = 0xd000,
+ ReservedMask = 0xd000,
+ RTSpecialName = 0x1000,
+ HasSecurity = 0x4000,
+ RequireSecObject = 0x8000,
+#if !MinimalReader
+ Extend = 0x01000000, // used for languages with type extensions, e.g. Sing#
+#endif
+ }
+ public enum ModuleKindFlags
+ { //TODO: rename this to just ModuleKind
+ ConsoleApplication,
+ WindowsApplication,
+ DynamicallyLinkedLibrary,
+ ManifestResourceFile,
+ UnmanagedDynamicallyLinkedLibrary
+ }
+ [Flags]
+ public enum ParameterFlags
+ {
+ None = 0x0000,
+ In = 0x0001,
+ Out = 0x0002,
+ Optional = 0x0010,
+ ReservedMask = 0xf000,
+ HasDefault = 0x1000,
+ HasFieldMarshal = 0x2000
+ }
+ [Flags]
+ public enum PEKindFlags
+ {
+ ILonly = 0x0001,
+ Requires32bits = 0x0002,
+ Requires64bits = 0x0004,
+ AMD = 0x0008
+ }
+ [Flags]
+ public enum PInvokeFlags
+ {
+ None = 0x0000,
+ NoMangle = 0x0001,
+ BestFitDisabled = 0x0020,
+ BestFitEnabled = 0x0010,
+ BestFitUseAsm = 0x0000,
+ BestFitMask = 0x0030,
+ CharSetMask = 0x0006,
+ CharSetNotSpec = 0x0000,
+ CharSetAns = 0x0002,
+ CharSetUnicode = 0x0004,
+ CharSetAuto = 0x0006,
+ SupportsLastError = 0x0040,
+ CallingConvMask = 0x0700,
+ CallConvWinapi = 0x0100,
+ CallConvCdecl = 0x0200,
+ CallConvStdcall = 0x0300,
+ CallConvThiscall = 0x0400,
+ CallConvFastcall = 0x0500,
+ ThrowOnUnmappableCharMask = 0x3000,
+ ThrowOnUnmappableCharEnabled = 0x1000,
+ ThrowOnUnmappableCharDisabled = 0x2000,
+ ThrowOnUnmappableCharUseAsm = 0x0000
+ }
+ [Flags]
+ public enum PropertyFlags
+ {
+ None = 0x0000,
+ SpecialName = 0x0200,
+ ReservedMask = 0xf400,
+ RTSpecialName = 0x0400,
+#if !MinimalReader
+ Extend = MethodFlags.Extend, // used for languages with type extensions, e.g. Sing#
+#endif
+ }
+ public enum PESection
+ {
+ Text,
+ SData,
+ TLS
+ };
+#if !MinimalReader
+ public enum ProcessorType
+ {
+ Any,
+ x86,
+ x64,
+ Itanium,
+ }
+#endif
+ [Flags]
+ public enum TypeFlags
+ {
+ None = 0x00000000,
+ VisibilityMask = 0x00000007,
+ NotPublic = 0x00000000,
+ Public = 0x00000001,
+ NestedPublic = 0x00000002,
+ NestedPrivate = 0x00000003,
+ NestedFamily = 0x00000004,
+ NestedAssembly = 0x00000005,
+ NestedFamANDAssem = 0x00000006,
+ NestedFamORAssem = 0x00000007,
+ LayoutMask = 0x00000018,
+ AutoLayout = 0x00000000,
+ SequentialLayout = 0x00000008,
+ ExplicitLayout = 0x00000010,
+ ClassSemanticsMask = 0x00000020,
+ Class = 0x00000000,
+ Interface = 0x00000020,
+ LayoutOverridden = 0x00000040, // even AutoLayout can be explicit or implicit
+ Abstract = 0x00000080,
+ Sealed = 0x00000100,
+ SpecialName = 0x00000400,
+ Import = 0x00001000,
+ Serializable = 0x00002000,
+ StringFormatMask = 0x00030000,
+ AnsiClass = 0x00000000,
+ UnicodeClass = 0x00010000,
+ AutoClass = 0x00020000,
+ BeforeFieldInit = 0x00100000,
+ ReservedMask = 0x00040800,
+ RTSpecialName = 0x00000800,
+ HasSecurity = 0x00040000,
+ Forwarder = 0x00200000, //The type is a stub left behind for backwards compatibility. References to this type are forwarded to another type by the CLR.
+#if !MinimalReader
+ Extend = 0x01000000, // used for languages with type extensions, e.g. Sing#
+#endif
+ }
+
+ public sealed class TrivialHashtable
+ {
+ struct HashEntry
+ {
+ public int Key;
+ public object Value;
+ }
+
+ private HashEntry[]/*!*/ entries;
+ private int count;
+
+ public TrivialHashtable()
+ {
+ this.entries = new HashEntry[16];
+ //this.count = 0;
+ }
+ private TrivialHashtable(HashEntry[]/*!*/ entries, int count)
+ {
+ this.entries = entries;
+ this.count = count;
+ }
+ public TrivialHashtable(int expectedEntries)
+ {
+ int initialSize = 16;
+ expectedEntries <<= 1;
+ while (initialSize < expectedEntries && initialSize > 0) initialSize <<= 1;
+ if (initialSize < 0) initialSize = 16;
+ this.entries = new HashEntry[initialSize];
+ //this.count = 0;
+ }
+ public int Count
+ {
+ get
+ {
+ return this.count;
+ }
+ }
+ private void Expand()
+ {
+ HashEntry[] oldEntries = this.entries;
+ int n = oldEntries.Length;
+ int m = n * 2;
+ if (m <= 0) return;
+ HashEntry[] entries = new HashEntry[m];
+ int count = 0;
+ for (int i = 0; i < n; i++)
+ {
+ int key = oldEntries[i].Key;
+ if (key <= 0) continue; //No entry (0) or deleted entry (-1)
+ object value = oldEntries[i].Value;
+ Debug.Assert(value != null);
+ int j = key & (m - 1);
+ int k = entries[j].Key;
+ while (true)
+ {
+ if (k == 0)
+ {
+ entries[j].Value = value;
+ entries[j].Key = key;
+ count++;
+ break;
+ }
+ j++; if (j >= m) j = 0;
+ k = entries[j].Key;
+ }
+ }
+ this.entries = entries;
+ this.count = count;
+ }
+ public object this[int key]
+ {
+ get
+ {
+ if (key <= 0) throw new ArgumentException(ExceptionStrings.KeyNeedsToBeGreaterThanZero, "key");
+ HashEntry[] entries = this.entries;
+ int n = entries.Length;
+ int i = key & (n - 1);
+ int k = entries[i].Key;
+ object result = null;
+ while (true)
+ {
+ if (k == key) { result = entries[i].Value; break; }
+ if (k == 0) break;
+ i++; if (i >= n) i = 0;
+ k = entries[i].Key;
+ }
+ return result;
+ }
+ set
+ {
+ if (key <= 0) throw new ArgumentException(ExceptionStrings.KeyNeedsToBeGreaterThanZero, "key");
+ HashEntry[] entries = this.entries;
+ int n = entries.Length;
+ int i = key & (n - 1);
+ int k = entries[i].Key;
+ while (true)
+ {
+ if (k == key || k == 0)
+ {
+ entries[i].Value = value;
+ if (k == 0)
+ {
+ if (value == null) { return; }
+ entries[i].Key = key;
+ if (++this.count > n / 2) this.Expand();
+ return;
+ }
+ if (value == null) entries[i].Key = -1;
+ return;
+ }
+ i++; if (i >= n) i = 0;
+ k = entries[i].Key;
+ }
+ }
+ }
+ public TrivialHashtable Clone()
+ {
+ HashEntry[] clonedEntries = (HashEntry[])this.entries.Clone();
+ //^ assume clonedEntries != null;
+ return new TrivialHashtable(clonedEntries, this.count);
+ }
+ }
+#if !FxCop
+ public
+#endif
+ sealed class TrivialHashtableUsingWeakReferences
+ {
+ struct HashEntry
+ {
+ public int Key;
+ public WeakReference Value;
+ }
+
+ private HashEntry[]/*!*/ entries;
+ private int count;
+
+ public TrivialHashtableUsingWeakReferences()
+ {
+ this.entries = new HashEntry[16];
+ //this.count = 0;
+ }
+ private TrivialHashtableUsingWeakReferences(HashEntry[]/*!*/ entries, int count)
+ {
+ this.entries = entries;
+ this.count = count;
+ }
+ public TrivialHashtableUsingWeakReferences(int expectedEntries)
+ {
+ int initialSize = 16;
+ expectedEntries <<= 1;
+ while (initialSize < expectedEntries && initialSize > 0) initialSize <<= 1;
+ if (initialSize < 0) initialSize = 16;
+ this.entries = new HashEntry[initialSize];
+ //this.count = 0;
+ }
+ public int Count
+ {
+ get
+ {
+ return this.count;
+ }
+ }
+ private void Expand()
+ {
+ HashEntry[] oldEntries = this.entries;
+ int n = oldEntries.Length;
+ int m = n * 2;
+ if (m <= 0) return;
+ HashEntry[] entries = new HashEntry[m];
+ int count = 0;
+ for (int i = 0; i < n; i++)
+ {
+ int key = oldEntries[i].Key;
+ if (key <= 0) continue; //No entry (0) or deleted entry (-1)
+ WeakReference value = oldEntries[i].Value;
+ Debug.Assert(value != null);
+ if (value == null || !value.IsAlive) continue; //Collected entry.
+ int j = key & (m - 1);
+ int k = entries[j].Key;
+ while (true)
+ {
+ if (k == 0)
+ {
+ entries[j].Value = value;
+ entries[j].Key = key;
+ count++;
+ break;
+ }
+ j++; if (j >= m) j = 0;
+ k = entries[j].Key;
+ }
+ }
+ this.entries = entries;
+ this.count = count;
+ }
+ private void Contract()
+ {
+ HashEntry[] oldEntries = this.entries;
+ int n = oldEntries.Length;
+ int m = n / 2;
+ if (m < 16) return;
+ HashEntry[] entries = new HashEntry[m];
+ int count = 0;
+ for (int i = 0; i < n; i++)
+ {
+ int key = oldEntries[i].Key;
+ if (key <= 0) continue; //No entry (0) or deleted entry (-1)
+ WeakReference value = oldEntries[i].Value;
+ Debug.Assert(value != null);
+ if (value == null || !value.IsAlive) continue; //Collected entry.
+ int j = key & (m - 1);
+ int k = entries[j].Key;
+ while (true)
+ {
+ if (k == 0)
+ {
+ entries[j].Value = value;
+ entries[j].Key = key;
+ count++;
+ break;
+ }
+ j++; if (j >= m) j = 0;
+ k = entries[j].Key;
+ }
+ }
+ this.entries = entries;
+ this.count = count;
+ }
+ private void WeedOutCollectedEntries()
+ {
+ HashEntry[] oldEntries = this.entries;
+ int n = oldEntries.Length;
+ HashEntry[] entries = new HashEntry[n];
+ int count = 0;
+ for (int i = 0; i < n; i++)
+ {
+ int key = oldEntries[i].Key;
+ if (key <= 0) continue; //No entry (0) or deleted entry (-1)
+ WeakReference value = oldEntries[i].Value;
+ Debug.Assert(value != null);
+ if (value == null || !value.IsAlive) continue; //Collected entry.
+ int j = key & (n - 1);
+ int k = entries[j].Key;
+ while (true)
+ {
+ if (k == 0)
+ {
+ entries[j].Value = value;
+ entries[j].Key = key;
+ count++;
+ break;
+ }
+ j++; if (j >= n) j = 0;
+ k = entries[j].Key;
+ }
+ }
+ this.entries = entries;
+ this.count = count;
+ }
+ public object this[int key]
+ {
+ get
+ {
+ if (key <= 0) throw new ArgumentException(ExceptionStrings.KeyNeedsToBeGreaterThanZero, "key");
+ HashEntry[] entries = this.entries;
+ int n = entries.Length;
+ int i = key & (n - 1);
+ int k = entries[i].Key;
+ object result = null;
+ while (true)
+ {
+ if (k == key)
+ {
+ WeakReference wref = entries[i].Value;
+ if (wref == null) { Debug.Assert(false); return null; }
+ result = wref.Target;
+ if (result != null) return result;
+ this.WeedOutCollectedEntries();
+ while (this.count < n / 4 && n > 16) { this.Contract(); n = this.entries.Length; }
+ return null;
+ }
+ if (k == 0) break;
+ i++; if (i >= n) i = 0;
+ k = entries[i].Key;
+ }
+ return result;
+ }
+ set
+ {
+ if (key <= 0) throw new ArgumentException(ExceptionStrings.KeyNeedsToBeGreaterThanZero, "key");
+ HashEntry[] entries = this.entries;
+ int n = entries.Length;
+ int i = key & (n - 1);
+ int k = entries[i].Key;
+ while (true)
+ {
+ if (k == key || k == 0)
+ {
+ if (value == null)
+ entries[i].Value = null;
+ else
+ entries[i].Value = new WeakReference(value);
+ if (k == 0)
+ {
+ if (value == null) return;
+ entries[i].Key = key;
+ if (++this.count > n / 2)
+ {
+ this.Expand(); //Could decrease this.count because of collected entries being deleted
+ while (this.count < n / 4 && n > 16) { this.Contract(); n = this.entries.Length; }
+ }
+ return;
+ }
+ if (value == null) entries[i].Key = -1;
+ return;
+ }
+ i++; if (i >= n) i = 0;
+ k = entries[i].Key;
+ }
+ }
+ }
+ public TrivialHashtableUsingWeakReferences Clone()
+ {
+ HashEntry[] clonedEntries = (HashEntry[])this.entries.Clone();
+ //^ assume clonedEntries != null;
+ return new TrivialHashtableUsingWeakReferences(clonedEntries, this.count);
+ }
+ }
+
+ public interface IUniqueKey
+ {
+ int UniqueId { get; }
+ }
+
+ /// <summary>
+ /// A node in an Abstract Syntax Tree.
+ /// </summary>
+ public abstract class Node : IUniqueKey
+ {
+#if !MinimalReader
+ public bool IsErroneous;
+#endif
+ /// <summary>
+ /// The region in the source code that contains the concrete syntax corresponding to this node in the Abstract Syntax Tree.
+ /// </summary>
+#if !FxCop
+ public SourceContext SourceContext;
+#else
+ internal SourceContext sourceContext;
+ public SourceContext SourceContext {
+ get{return this.sourceContext;}
+ internal set{this.sourceContext = value;}
+ }
+#endif
+#if DEBUG && !MinimalReader
+ public string DebugLabel; // useful for debugging.
+#endif
+ protected Node(NodeType nodeType)
+ {
+ this.NodeType = nodeType;
+ }
+ private NodeType nodeType;
+ /// <summary>
+ /// A scalar tag that identifies the concrete type of the node. This is provided to allow efficient type membership tests that
+ /// facilitate tree traversal.
+ /// </summary>
+ public NodeType NodeType
+ {
+ get { return this.nodeType; }
+ set { this.nodeType = value; }
+ }
+ private static int uniqueKeyCounter;
+ private int uniqueKey;
+ /// <summary>
+ /// An integer that uniquely identifies this node. This provides an efficient equality test to facilitate hashing.
+ /// Do not override this.
+ /// </summary>
+ public virtual int UniqueKey
+ {
+ get
+ {
+ if (this.uniqueKey == 0)
+ {
+ TryAgain:
+ int c = Node.uniqueKeyCounter;
+ int cp1 = c + 17;
+ if (cp1 <= 0) cp1 = 1000000;
+ if (System.Threading.Interlocked.CompareExchange(ref Node.uniqueKeyCounter, cp1, c) != c) goto TryAgain;
+ this.uniqueKey = cp1;
+ }
+ return this.uniqueKey;
+ }
+ }
+ /// <summary>
+ /// Makes a shallow copy of the node.
+ /// </summary>
+ /// <returns>A shallow copy of the node</returns>
+ public virtual Node/*!*/ Clone()
+ {
+ Node result = (Node)this.MemberwiseClone();
+ result.uniqueKey = 0;
+ return result;
+ }
+#if !MinimalReader
+ public virtual object GetVisitorFor(object/*!*/ callingVisitor, string/*!*/ visitorClassName)
+ {
+ if (callingVisitor == null || visitorClassName == null) { Debug.Fail(""); return null; }
+ return Node.GetVisitorFor(this.GetType(), callingVisitor, visitorClassName);
+ }
+ private static Hashtable VisitorTypeFor; //contains weak references
+ private static Object GetVisitorFor(System.Type/*!*/ nodeType, object/*!*/ callingVisitor, string/*!*/ visitorClassName)
+ {
+ if (nodeType == null || callingVisitor == null || visitorClassName == null) { Debug.Fail(""); return null; }
+ if (Node.VisitorTypeFor == null) Node.VisitorTypeFor = new Hashtable();
+ string customVisitorClassName = visitorClassName;
+ if (visitorClassName.IndexOf('.') < 0) customVisitorClassName = nodeType.Namespace + "." + visitorClassName;
+ if (customVisitorClassName == callingVisitor.GetType().FullName)
+ {
+ Debug.Assert(false); //This must be a bug, the calling visitor is the one that should handle the nodeType
+ return null;
+ }
+ System.Reflection.AssemblyName visitorAssemblyName = null;
+ System.Reflection.Assembly assembly = null;
+ WeakReference wref = (WeakReference)Node.VisitorTypeFor[customVisitorClassName];
+ Type visitorType = wref == null ? null : (System.Type)wref.Target;
+ if (visitorType == typeof(object)) return null;
+ string callerDirectory = null;
+ if (visitorType == null)
+ {
+ assembly = nodeType.Assembly;
+ if (assembly == null) return null;
+ visitorType = assembly.GetType(customVisitorClassName, false);
+ }
+ if (visitorType == null)
+ {
+ //^ assert assembly != null;
+ if (assembly.Location == null) return null;
+ callerDirectory = Path.GetDirectoryName(assembly.Location);
+ visitorAssemblyName = new System.Reflection.AssemblyName();
+ visitorAssemblyName.Name = "Visitors";
+ visitorAssemblyName.CodeBase = "file:///" + Path.Combine(callerDirectory, "Visitors.dll");
+ try
+ {
+ assembly = System.Reflection.Assembly.Load(visitorAssemblyName);
+ }
+ catch { }
+ if (assembly != null)
+ visitorType = assembly.GetType(customVisitorClassName, false);
+ if (visitorType == null)
+ {
+ visitorAssemblyName.Name = customVisitorClassName;
+ visitorAssemblyName.CodeBase = "file:///" + Path.Combine(callerDirectory, customVisitorClassName + ".dll");
+ try
+ {
+ assembly = System.Reflection.Assembly.Load(visitorAssemblyName);
+ }
+ catch { }
+ if (assembly != null)
+ visitorType = assembly.GetType(customVisitorClassName, false);
+ }
+ }
+ if (visitorType == null)
+ {
+ //Put fake entry into hashtable to short circuit future lookups
+ visitorType = typeof(object);
+ assembly = nodeType.Assembly;
+ }
+ if (assembly != null)
+ { //Only happens if there was a cache miss
+ lock (Node.VisitorTypeFor)
+ {
+ Node.VisitorTypeFor[customVisitorClassName] = new WeakReference(visitorType);
+ }
+ }
+ if (visitorType == typeof(object)) return null;
+ try
+ {
+ return System.Activator.CreateInstance(visitorType, new object[] { callingVisitor });
+ }
+ catch { }
+ return null;
+ }
+#endif
+ int IUniqueKey.UniqueId { get { return this.UniqueKey; } }
+#if MinimalReader
+ // Return a constant value for IsNormalized in the binary-only
+ // reader. This results in less code churn elsewhere.
+ internal bool IsNormalized{get{return true;}}
+#endif
+ }
+#if !MinimalReader
+ public abstract class ErrorNode : Node
+ {
+ public int Code;
+ public string[] MessageParameters;
+
+ protected ErrorNode(int code, params string[] messageParameters)
+ : base(NodeType.Undefined)
+ {
+ this.Code = code;
+ this.MessageParameters = messageParameters;
+ }
+ public virtual string GetErrorNumber()
+ {
+ return this.Code.ToString("0000");
+ }
+ public string GetMessage()
+ {
+ return this.GetMessage(null);
+ }
+#if ExtendedRuntime
+ [return: Microsoft.Contracts.NotNull]
+#endif
+ public abstract string GetMessage(System.Globalization.CultureInfo culture);
+ public virtual string GetMessage(string key, System.Resources.ResourceManager rm, System.Globalization.CultureInfo culture)
+ {
+ if (rm == null || key == null) return null;
+ string localizedString = rm.GetString(key, culture);
+ if (localizedString == null) localizedString = key;
+ string[] messageParameters = this.MessageParameters;
+ if (messageParameters == null || messageParameters.Length == 0) return localizedString;
+ return string.Format(localizedString, messageParameters);
+ }
+ public abstract int Severity
+ {
+ get;
+ }
+ public static int GetCountAtSeverity(ErrorNodeList errors, int minSeverity, int maxSeverity)
+ {
+ if (errors == null) return 0;
+ int n = 0;
+ for (int i = 0; i < errors.Count; i++)
+ {
+ ErrorNode e = errors[i];
+ if (e == null)
+ continue;
+ int s = e.Severity;
+ if (minSeverity <= s && s <= maxSeverity)
+ n++;
+ }
+ return n;
+ }
+ }
+ public class Expose : Statement
+ {
+ public Expression Instance;
+ public Block Body;
+ public bool IsLocal;
+ public Expose(NodeType nodeType)
+ : base(nodeType)
+ {
+ }
+ }
+ public class Acquire : Statement
+ {
+ public bool ReadOnly;
+ public Statement Target;
+ public Expression Condition;
+ public Expression ConditionFunction;
+ public Block Body;
+ public BlockScope ScopeForTemporaryVariable;
+ public Acquire()
+ : base(NodeType.Acquire)
+ {
+ }
+ }
+#endif
+ public class Expression : Node
+ {
+ private TypeNode type;
+#if FxCop
+ internal int ILOffset;
+#endif
+ public Expression(NodeType nodeType)
+ : base(nodeType)
+ {
+ }
+ public Expression(NodeType nodeType, TypeNode type)
+ : base(nodeType)
+ {
+ this.type = type;
+ }
+ public virtual TypeNode Type
+ {
+ get { return this.type; }
+ set { this.type = value; }
+ }
+ }
+#if !MinimalReader
+ public class ExpressionSnippet : Expression
+ {
+ public IParserFactory ParserFactory;
+
+ public ExpressionSnippet()
+ : base(NodeType.ExpressionSnippet)
+ {
+ }
+ public ExpressionSnippet(IParserFactory parserFactory, SourceContext sctx)
+ : base(NodeType.ExpressionSnippet)
+ {
+ this.ParserFactory = parserFactory;
+ this.SourceContext = sctx;
+ }
+ }
+#endif
+ public class MemberBinding : Expression
+ {
+ private int alignment;
+ private Member boundMember;
+#if !MinimalReader
+ public Expression BoundMemberExpression;
+#endif
+ private Expression targetObject;
+ private bool @volatile;
+ public MemberBinding()
+ : base(NodeType.MemberBinding)
+ {
+ }
+ public MemberBinding(Expression targetObject, Member/*!*/ boundMember)
+ : this(targetObject, boundMember, false, -1)
+ {
+ if (boundMember is Field) this.Volatile = ((Field)boundMember).IsVolatile;
+ }
+#if !MinimalReader
+ public MemberBinding(Expression targetObject, Member/*!*/ boundMember, Expression boundMemberExpression)
+ : this(targetObject, boundMember, false, -1)
+ {
+ if (boundMember is Field) this.Volatile = ((Field)boundMember).IsVolatile;
+ this.BoundMemberExpression = boundMemberExpression;
+ }
+ public MemberBinding(Expression targetObject, Member/*!*/ boundMember, SourceContext sctx)
+ : this(targetObject, boundMember, false, -1)
+ {
+ if (boundMember is Field) this.Volatile = ((Field)boundMember).IsVolatile;
+ this.SourceContext = sctx;
+ }
+ public MemberBinding(Expression targetObject, Member/*!*/ boundMember, SourceContext sctx, Expression boundMemberExpression)
+ : this(targetObject, boundMember, false, -1)
+ {
+ if (boundMember is Field) this.Volatile = ((Field)boundMember).IsVolatile;
+ this.SourceContext = sctx;
+ this.BoundMemberExpression = boundMemberExpression;
+ }
+#endif
+ public MemberBinding(Expression targetObject, Member/*!*/ boundMember, bool @volatile, int alignment)
+ : base(NodeType.MemberBinding)
+ {
+ Debug.Assert(boundMember != null);
+ this.alignment = alignment;
+ this.boundMember = boundMember;
+ this.targetObject = targetObject;
+ this.@volatile = @volatile;
+ switch (boundMember.NodeType)
+ {
+ case NodeType.Field: this.Type = ((Field)boundMember).Type; break;
+ case NodeType.Method: this.Type = ((Method)boundMember).ReturnType; break;
+ case NodeType.Event: this.Type = ((Event)boundMember).HandlerType; break;
+ default: this.Type = boundMember as TypeNode; break;
+ }
+ }
+ public int Alignment
+ {
+ get { return this.alignment; }
+ set { this.alignment = value; }
+ }
+ public Member BoundMember
+ {
+ get { return this.boundMember; }
+ set { this.boundMember = value; }
+ }
+ public Expression TargetObject
+ {
+ get { return this.targetObject; }
+ set { this.targetObject = value; }
+ }
+ public bool Volatile
+ {
+ get { return this.@volatile; }
+ set { this.@volatile = value; }
+ }
+ }
+ public class AddressDereference : Expression
+ {
+ private Expression address;
+ private int alignment;
+ private bool isVolatile;
+#if !MinimalReader
+ public enum ExplicitOp { None = 0, Star, Arrow }
+ private ExplicitOp explicitOperation; // was explicit in source (* or ->)
+#endif
+ public AddressDereference()
+ : base(NodeType.AddressDereference)
+ {
+ }
+ public AddressDereference(Expression address, TypeNode type)
+ : this(address, type, false, -1)
+ {
+ }
+#if !MinimalReader
+ public AddressDereference(Expression address, TypeNode type, SourceContext sctx)
+ : this(address, type, false, -1, sctx)
+ {
+ }
+#endif
+ public AddressDereference(Expression address, TypeNode type, bool isVolatile, int alignment)
+ : base(NodeType.AddressDereference)
+ {
+ this.address = address;
+ this.alignment = alignment;
+ this.Type = type;
+ this.isVolatile = isVolatile;
+ }
+#if !MinimalReader
+ public AddressDereference(Expression address, TypeNode type, bool Volatile, int alignment, SourceContext sctx)
+ : base(NodeType.AddressDereference)
+ {
+ this.address = address;
+ this.alignment = alignment;
+ this.Type = type;
+ this.isVolatile = Volatile;
+ this.SourceContext = sctx;
+ }
+#endif
+ public Expression Address
+ {
+ get { return this.address; }
+ set { this.address = value; }
+ }
+ public int Alignment
+ {
+ get { return this.alignment; }
+ set { this.alignment = value; }
+ }
+ public bool Volatile
+ {
+ get { return this.isVolatile; }
+ set { this.isVolatile = value; }
+ }
+#if !MinimalReader
+ public bool Explicit
+ {
+ get { return this.explicitOperation != ExplicitOp.None; }
+ }
+ public ExplicitOp ExplicitOperator
+ {
+ get { return this.explicitOperation; }
+ set { this.explicitOperation = value; }
+ }
+#endif
+ }
+ public class UnaryExpression : Expression
+ {
+ private Expression operand;
+ public UnaryExpression()
+ : base(NodeType.Nop)
+ {
+ }
+ public UnaryExpression(Expression operand, NodeType nodeType)
+ : base(nodeType)
+ {
+ this.Operand = operand;
+ }
+#if !MinimalReader
+ public UnaryExpression(Expression operand, NodeType nodeType, SourceContext sctx)
+ : base(nodeType)
+ {
+ this.operand = operand;
+ this.SourceContext = sctx;
+ }
+#endif
+ public UnaryExpression(Expression operand, NodeType nodeType, TypeNode type)
+ : base(nodeType)
+ {
+ this.operand = operand;
+ this.Type = type;
+ }
+#if !MinimalReader
+ public UnaryExpression(Expression operand, NodeType nodeType, TypeNode type, SourceContext sctx)
+ : base(nodeType)
+ {
+ this.operand = operand;
+ this.Type = type;
+ this.SourceContext = sctx;
+ }
+#endif
+ public Expression Operand
+ {
+ get { return this.operand; }
+ set { this.operand = value; }
+ }
+ }
+#if !MinimalReader
+ public class PrefixExpression : Expression
+ {
+ public Expression Expression;
+ public NodeType Operator;
+ public Method OperatorOverload;
+ public PrefixExpression()
+ : base(NodeType.PrefixExpression)
+ {
+ }
+ public PrefixExpression(Expression expression, NodeType Operator, SourceContext sourceContext)
+ : base(NodeType.PrefixExpression)
+ {
+ this.Expression = expression;
+ this.Operator = Operator;
+ this.SourceContext = sourceContext;
+ }
+ }
+ public class PostfixExpression : Expression
+ {
+ public Expression Expression;
+ public NodeType Operator;
+ public Method OperatorOverload;
+ public PostfixExpression()
+ : base(NodeType.PostfixExpression)
+ {
+ }
+ public PostfixExpression(Expression expression, NodeType Operator, SourceContext sourceContext)
+ : base(NodeType.PostfixExpression)
+ {
+ this.Expression = expression;
+ this.Operator = Operator;
+ this.SourceContext = sourceContext;
+ }
+ }
+#endif
+ public class BinaryExpression : Expression
+ {
+ private Expression operand1;
+ private Expression operand2;
+ public BinaryExpression()
+ : base(NodeType.Nop)
+ {
+ }
+ public BinaryExpression(Expression operand1, Expression operand2, NodeType nodeType)
+ : base(nodeType)
+ {
+ this.operand1 = operand1;
+ this.operand2 = operand2;
+ }
+ public BinaryExpression(Expression operand1, Expression operand2, NodeType nodeType, TypeNode resultType)
+ : base(nodeType)
+ {
+ this.operand1 = operand1;
+ this.operand2 = operand2;
+ this.Type = resultType;
+ }
+#if !MinimalReader
+ public BinaryExpression(Expression operand1, Expression operand2, NodeType nodeType, SourceContext ctx)
+ : base(nodeType)
+ {
+ this.operand1 = operand1;
+ this.operand2 = operand2;
+ this.SourceContext = ctx;
+ }
+ public BinaryExpression(Expression operand1, Expression operand2, NodeType nodeType, TypeNode resultType, SourceContext ctx)
+ : base(nodeType)
+ {
+ this.operand1 = operand1;
+ this.operand2 = operand2;
+ this.Type = resultType;
+ this.SourceContext = ctx;
+ }
+#endif
+ public Expression Operand1
+ {
+ get { return this.operand1; }
+ set { this.operand1 = value; }
+ }
+ public Expression Operand2
+ {
+ get { return this.operand2; }
+ set { this.operand2 = value; }
+ }
+ }
+ public class TernaryExpression : Expression
+ {
+ private Expression operand1;
+ private Expression operand2;
+ private Expression operand3;
+ public TernaryExpression()
+ : base(NodeType.Nop)
+ {
+ }
+ public TernaryExpression(Expression operand1, Expression operand2, Expression operand3, NodeType nodeType, TypeNode resultType)
+ : base(nodeType)
+ {
+ this.operand1 = operand1;
+ this.operand2 = operand2;
+ this.operand3 = operand3;
+ this.Type = resultType;
+ }
+ public Expression Operand1
+ {
+ get { return this.operand1; }
+ set { this.operand1 = value; }
+ }
+ public Expression Operand2
+ {
+ get { return this.operand2; }
+ set { this.operand2 = value; }
+ }
+ public Expression Operand3
+ {
+ get { return this.operand3; }
+ set { this.operand3 = value; }
+ }
+ }
+ public abstract class NaryExpression : Expression
+ {
+#if !FxCop
+ public ExpressionList Operands;
+#else
+ private ExpressionList operands;
+ public ExpressionList Operands {
+ get {return this.operands;}
+ internal set{this.operands = value;}
+ }
+#endif
+ protected NaryExpression()
+ : base(NodeType.Nop)
+ {
+ }
+ protected NaryExpression(ExpressionList operands, NodeType nodeType)
+ : base(nodeType)
+ {
+ this.Operands = operands;
+ }
+ }
+#if !MinimalReader
+ public class ApplyToAll : BinaryExpression
+ {
+ public Local ElementLocal;
+ public Method ResultIterator;
+ public ApplyToAll()
+ : base(null, null, NodeType.ApplyToAll)
+ {
+ }
+ public ApplyToAll(Expression operand1, Expression operand2)
+ : base(operand1, operand2, NodeType.ApplyToAll)
+ {
+ }
+ public ApplyToAll(Expression operand1, Expression operand2, SourceContext ctx)
+ : base(operand1, operand2, NodeType.ApplyToAll)
+ {
+ this.SourceContext = ctx;
+ }
+ }
+#endif
+ public class NamedArgument : Expression
+ {
+ private bool isCustomAttributeProperty;
+ private Identifier name;
+ private Expression value;
+ private bool valueIsBoxed;
+ public NamedArgument()
+ : base(NodeType.NamedArgument)
+ {
+ }
+ public NamedArgument(Identifier name, Expression value)
+ : base(NodeType.NamedArgument)
+ {
+ this.Name = name;
+ this.Value = value;
+ }
+#if !MinimalReader
+ public NamedArgument(Identifier name, Expression value, SourceContext ctx)
+ : base(NodeType.NamedArgument)
+ {
+ this.Name = name;
+ this.Value = value;
+ this.SourceContext = ctx;
+ }
+#endif
+ public bool IsCustomAttributeProperty
+ { //TODO: rename this to IsProperty
+ get { return this.isCustomAttributeProperty; }
+ set { this.isCustomAttributeProperty = value; }
+ }
+ public Identifier Name
+ {
+ get { return this.name; }
+ set { this.name = value; }
+ }
+ public Expression Value
+ {
+ get { return this.value; }
+ set { this.value = value; }
+ }
+ public bool ValueIsBoxed
+ {
+ get { return this.valueIsBoxed; }
+ set { this.valueIsBoxed = value; }
+ }
+ }
+ /// <summary>
+ /// This an Expression wrapper for compile time constants. It is assumed to be correct by construction.
+ /// In Normalized IR, the wrapped value must be a primitive numeric type or an enum or a string or null.
+ /// If used in custom attributes, types are also allowed as well as single dimensional arrays of other allowed types.
+ /// If the wrapped value is null, any reference type is allowed, except in custom attributes, where it must be Type or String.
+ /// </summary>
+ public class Literal : Expression
+ {
+ private object value;
+#if !MinimalReader
+ public bool TypeWasExplicitlySpecifiedInSource;
+ public Expression SourceExpression;
+#endif
+ public Literal()
+ : base(NodeType.Literal)
+ {
+ }
+#if !NoReflection
+ public Literal(object Value)
+ : base(NodeType.Literal)
+ {
+ this.value = Value;
+ }
+#endif
+ public Literal(object value, TypeNode type)
+ : base(NodeType.Literal)
+ {
+ this.value = value;
+ this.Type = type;
+ }
+ public Literal(object value, TypeNode type, SourceContext sourceContext)
+ : base(NodeType.Literal)
+ {
+ this.value = value;
+ this.SourceContext = sourceContext;
+ this.Type = type;
+ }
+ /// <summary>
+ /// Holds the wrapped compile time constant value.
+ /// </summary>
+ public object Value
+ {
+ get { return this.value; }
+ }
+ public override string ToString()
+ {
+ if (this.Value == null) return "Literal for null";
+ return this.Value.ToString();
+ }
+#if !NoWriter
+ public static bool IsNullLiteral(Expression expr)
+ {
+ Literal lit = expr as Literal;
+ if (lit == null) return false;
+ if (lit.Type != CoreSystemTypes.Object || lit.Value != null) return false;
+ return true;
+ }
+ //TODO: replace these with properties that freshly allocate them. It appears that Literals sometimes get clobbered.
+ public static Literal DoubleOne;
+ public static Literal False;
+ public static Literal Int32MinusOne;
+ public static Literal Int32Zero;
+ public static Literal Int32One;
+ public static Literal Int32Two;
+ public static Literal Int32Sixteen;
+ public static Literal Int64Zero;
+ public static Literal Int64One;
+ public static Literal Null;
+ public static Literal SingleOne;
+ public static Literal True;
+
+ public static void Initialize()
+ {
+ Literal.DoubleOne = new Literal(1.0, CoreSystemTypes.Double);
+ Literal.False = new Literal(false, CoreSystemTypes.Boolean);
+ Literal.Int32MinusOne = new Literal(-1, CoreSystemTypes.Int32);
+ Literal.Int32Zero = new Literal(0, CoreSystemTypes.Int32);
+ Literal.Int32One = new Literal(1, CoreSystemTypes.Int32);
+ Literal.Int32Two = new Literal(2, CoreSystemTypes.Int32);
+ Literal.Int32Sixteen = new Literal(16, CoreSystemTypes.Int32);
+ Literal.Int64Zero = new Literal(0L, CoreSystemTypes.Int64);
+ Literal.Int64One = new Literal(1L, CoreSystemTypes.Int64);
+ Literal.Null = new Literal(null, CoreSystemTypes.Object);
+ Literal.SingleOne = new Literal(1.0f, CoreSystemTypes.Single);
+ Literal.True = new Literal(true, CoreSystemTypes.Boolean);
+ }
+ public static void ClearStatics()
+ {
+ Literal.DoubleOne = null;
+ Literal.False = null;
+ Literal.Int32MinusOne = null;
+ Literal.Int32Zero = null;
+ Literal.Int32One = null;
+ Literal.Int32Two = null;
+ Literal.Int32Sixteen = null;
+ Literal.Int64Zero = null;
+ Literal.Int64One = null;
+ Literal.Null = null;
+ Literal.SingleOne = null;
+ Literal.True = null;
+ }
+#endif
+ }
+ public class This : Parameter
+ {
+ public This()
+ {
+ this.NodeType = NodeType.This;
+ this.Name = StandardIds.This;
+ }
+ public This(TypeNode type)
+ {
+ this.NodeType = NodeType.This;
+ this.Name = StandardIds.This;
+ this.Type = type;
+ }
+#if !MinimalReader
+ public bool IsCtorCall = false;
+ public This(SourceContext sctx, bool isCtorCall)
+ {
+ this.NodeType = NodeType.This;
+ this.Name = StandardIds.This;
+ this.SourceContext = sctx;
+ this.IsCtorCall = isCtorCall;
+ }
+ public This(TypeNode type, SourceContext sctx)
+ {
+ this.NodeType = NodeType.This;
+ this.Name = StandardIds.This;
+ this.Type = type;
+ this.SourceContext = sctx;
+ }
+ public override bool Equals(object obj)
+ {
+ ThisBinding binding = obj as ThisBinding;
+ return obj == this || binding != null && binding.BoundThis == this;
+ }
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+#endif
+#if ExtendedRuntime
+ public override bool IsUniversallyDelayed {
+ get {
+ if (this.DeclaringMethod is InstanceInitializer && this.DeclaringMethod.DeclaringType != null &&
+ !this.DeclaringMethod.DeclaringType.IsValueType) {
+ // by default, class constructors should be delayed
+ return !(this.DeclaringMethod.GetAttribute(ExtendedRuntimeTypes.NotDelayedAttribute) != null);
+ }
+ return (this.DeclaringMethod.GetAttribute(ExtendedRuntimeTypes.DelayedAttribute) != null);
+ }
+ }
+
+#endif
+ }
+#if !MinimalReader
+ public class ThisBinding : This, IUniqueKey
+ {
+ public This/*!*/ BoundThis;
+ public ThisBinding(This/*!*/ boundThis, SourceContext sctx)
+ {
+ if (boundThis == null) throw new ArgumentNullException("boundThis");
+ this.BoundThis = boundThis;
+ this.SourceContext = sctx;
+ this.Type = boundThis.Type;
+ this.Name = boundThis.Name;
+ this.TypeExpression = boundThis.TypeExpression;
+ this.Attributes = boundThis.Attributes;
+ this.DefaultValue = boundThis.DefaultValue;
+ this.Flags = boundThis.Flags;
+ this.MarshallingInformation = boundThis.MarshallingInformation;
+ this.DeclaringMethod = boundThis.DeclaringMethod;
+ this.ParameterListIndex = boundThis.ParameterListIndex;
+ this.ArgumentListIndex = boundThis.ArgumentListIndex;
+ //^ base();
+ }
+ public override int GetHashCode()
+ {
+ return this.BoundThis.GetHashCode();
+ }
+ public override bool Equals(object obj)
+ {
+ ThisBinding pb = obj as ThisBinding;
+ if (pb != null)
+ return this.BoundThis.Equals(pb.BoundThis);
+ else
+ return this.BoundThis.Equals(obj);
+ }
+ int IUniqueKey.UniqueId
+ {
+ get { return this.BoundThis.UniqueKey; }
+ }
+ /// <summary>
+ /// Must forward type to underlying binding, since ThisBindings get built at times when
+ /// the bound This node does not have its final type yet.
+ /// </summary>
+ public override TypeNode Type
+ {
+ get
+ {
+ return BoundThis.Type;
+ }
+ set
+ {
+ BoundThis.Type = value;
+ }
+ }
+ }
+ public class Base : Expression
+ {
+ /// <summary>
+ /// When the source uses the C# compatibility mode, base calls cannot be put after non-null
+ /// field initialization, but must be put before the body. But the user can specify where
+ /// the base ctor call should be performed by using "base;" as a marker. During parsing
+ /// this flag is set so the right code transformations can be performed at code generation.
+ /// </summary>
+ public bool UsedAsMarker;
+ public bool IsCtorCall = false;
+ public Base()
+ : base(NodeType.Base)
+ {
+ }
+ public Base(SourceContext sctx, bool isCtorCall)
+ : base(NodeType.Base)
+ {
+ this.SourceContext = sctx;
+ this.IsCtorCall = isCtorCall;
+ }
+ }
+ public class ImplicitThis : Expression
+ {
+ public int LexLevel;
+ public Class MostNestedScope;
+ public ImplicitThis()
+ : base(NodeType.ImplicitThis)
+ {
+ }
+ public ImplicitThis(Class mostNestedScope, int lexLevel)
+ : base(NodeType.ImplicitThis)
+ {
+ this.LexLevel = lexLevel;
+ this.MostNestedScope = mostNestedScope;
+ }
+ }
+ public class CurrentClosure : Expression
+ {
+ public Method Method;
+ public CurrentClosure()
+ : base(NodeType.CurrentClosure)
+ {
+ }
+ public CurrentClosure(Method method, TypeNode type)
+ : base(NodeType.CurrentClosure)
+ {
+ this.Method = method;
+ this.Type = type;
+ }
+ public CurrentClosure(Method method, TypeNode type, SourceContext sctx)
+ : base(NodeType.CurrentClosure)
+ {
+ this.Method = method;
+ this.Type = type;
+ this.SourceContext = sctx;
+ }
+ }
+ public class SetterValue : Expression
+ {
+ public SetterValue()
+ : base(NodeType.SetterValue)
+ {
+ }
+ }
+#endif
+ public class Identifier : Expression
+ {
+ private int hashCode;
+ internal int length;
+ private string name;
+ private int offset;
+#if !FxCop
+ private DocumentText text;
+#endif
+#if !MinimalReader
+ public Identifier Prefix;
+#endif
+ /// <summary>An identifier with the empty string ("") as its value.</summary>
+ public static readonly Identifier/*!*/ Empty = new Identifier("");
+#if !FxCop
+ private Identifier(DocumentText/*!*/ text, int offset, int length)
+ : base(NodeType.Identifier)
+ {
+ this.text = text;
+ this.offset = offset;
+ this.length = length;
+ ulong hcode = 0;
+ for (int i = offset, n = length + i; i < n; i++)
+ {
+ char ch = text[i];
+ hcode = hcode * 17 + ch;
+ }
+ this.hashCode = ((int)hcode) & int.MaxValue;
+ }
+ public static Identifier/*!*/ For(SourceContext sctx)
+ {
+ DocumentText text = null;
+ if (sctx.Document != null) text = sctx.Document.Text;
+ if (text == null) text = new DocumentText("");
+ Identifier id = new Identifier(text, sctx.StartPos, sctx.EndPos - sctx.StartPos);
+ id.SourceContext = sctx;
+ return id;
+ }
+#endif
+ public Identifier(string name)
+ : base(NodeType.Identifier)
+ {
+ if (name == null) name = "";
+ this.name = name;
+ int n = this.length = name.Length;
+ ulong hcode = 0;
+ for (int i = 0; i < n; i++)
+ {
+ char ch = name[i];
+ hcode = hcode * 17 + ch;
+ }
+ this.hashCode = ((int)hcode) & int.MaxValue;
+ }
+#if !MinimalReader
+ public Identifier(string name, SourceContext sctx)
+ : this(name)
+ {
+ this.SourceContext = sctx;
+ }
+#endif
+ public static Identifier/*!*/ For(string/*!*/ name)
+ {
+ return new Identifier(name);
+ }
+ private unsafe Identifier(byte* pointer, int offset)
+ : base(NodeType.Identifier)
+ {
+ this.offset = offset;
+ bool isASCII = true;
+ int length = 0;
+ ulong hcode = 0;
+ for (int i = offset; ; i++)
+ {
+ byte b = *(pointer + i);
+ if (b == 0) break;
+ if ((b & 0x80) != 0) isASCII = false;
+ hcode = hcode * 17 + b;
+ length++;
+ }
+ if (isASCII)
+ {
+ this.hashCode = ((int)hcode) & int.MaxValue;
+ this.length = length;
+ this.name = new string((sbyte*)pointer, offset, length, Encoding.ASCII);
+ return;
+ }
+ hcode = 0;
+ string name = this.name = new string((sbyte*)pointer, offset, length, Encoding.UTF8);
+ for (int i = 0, n = this.length = name.Length; i < n; i++)
+ {
+ char ch = name[i];
+ hcode = hcode * 17 + ch;
+ }
+ this.hashCode = ((int)hcode) & int.MaxValue;
+ }
+ /// <summary>
+ /// Use when pointer+offset points to a null terminated string of UTF8 code points.
+ /// </summary>
+ internal unsafe static Identifier/*!*/ For(byte* pointer, int offset)
+ {
+ //TODO: first look for identifier in cache
+ return new Identifier(pointer, offset);
+ }
+
+ private unsafe Identifier(byte* pointer, uint length)
+ : base(NodeType.Identifier)
+ {
+ //this.offset = 0;
+ this.length = (int)length;
+ ulong hcode = 0;
+ for (uint i = 0; i < length; i++)
+ {
+ byte b = *(pointer + i);
+ if ((b & 0x80) != 0) goto doUTF8decoding;
+ hcode = hcode * 17 + b;
+ }
+ this.hashCode = ((int)hcode) & int.MaxValue;
+ this.name = new string((sbyte*)pointer, 0, this.length, Encoding.ASCII);
+ return;
+ doUTF8decoding:
+ string name = this.name = new string((sbyte*)pointer, 0, this.length, Encoding.UTF8);
+ for (int i = 0, n = this.length = name.Length; i < n; i++)
+ {
+ char ch = name[i];
+ hcode = hcode * 17 + ch;
+ }
+ this.hashCode = ((int)hcode) & int.MaxValue;
+ }
+ /// <summary>
+ /// Use when pointer points to a string of UTF8 code points of a given length
+ /// </summary>
+ internal unsafe static Identifier/*!*/ For(byte* pointer, uint length)
+ {
+ //TODO: first look for identifier in cache
+ return new Identifier(pointer, length);
+ }
+ private static readonly object/*!*/ Lock = new object();
+ private struct CanonicalIdentifier
+ {
+ internal string/*!*/ Name;
+ internal int UniqueIdKey;
+ internal int HashCode;
+
+ internal CanonicalIdentifier(string/*!*/ name, int uniqueIdKey, int hashCode)
+ {
+ this.Name = name;
+ this.UniqueIdKey = uniqueIdKey;
+ this.HashCode = hashCode;
+ }
+ }
+ private static CanonicalIdentifier[]/*!*/ HashTable = new CanonicalIdentifier[16 * 1024];
+ private static int count;
+ private int GetUniqueIdKey()
+ {
+ lock (Identifier.Lock)
+ {
+ int hcode = this.hashCode;
+ CanonicalIdentifier[] hTable = Identifier.HashTable;
+ int length = hTable.Length;
+ int i = hcode % length;
+ CanonicalIdentifier id = hTable[i];
+ while (id.Name != null)
+ {
+ if (this.HasSameNameAs(id)) return id.UniqueIdKey;
+ i = (i + 1) % length;
+ id = hTable[i];
+ }
+ int count = Identifier.count;
+ int countp1 = count + 1;
+ Identifier.count = countp1;
+ string name = this.Name; //Get a local copy of the name and drop any reference to a DocumentText instance
+ hTable[i] = new CanonicalIdentifier(name, countp1, hcode);
+ if (countp1 > length / 2) Rehash(); //Threshold exceeded, need to rehash
+ return countp1;
+ }
+ }
+ private unsafe bool HasSameNameAs(CanonicalIdentifier id)
+ {
+ int myLength = this.length;
+ int idLength = id.Name.Length;
+ if (myLength != idLength) return false;
+ string myName = this.name;
+ string idName = id.Name;
+#if !FxCop
+ if (myName == null)
+ {
+ int myOffset = this.offset;
+ if (this.text != null && this.text.Equals(idName, myOffset, myLength))
+ {
+ this.name = idName;
+ this.text = null;
+ return true;
+ }
+ return false;
+ }
+#endif
+ return myName == idName;
+ }
+ public string/*!*/ Name
+ { //TODO: need a better name for this property
+ get
+ {
+#if !FxCop
+ if (this.name != null) return this.name;
+ lock (this)
+ {
+ if (this.name != null) return this.name;
+ //^ assume this.text != null;
+ int length = this.length;
+ int offset = this.offset;
+ this.name = this.text.Substring(offset, length);
+ this.text = null;
+ return this.name;
+ }
+#else
+ return this.name;
+#endif
+ }
+ }
+ private static void Rehash()
+ {
+ CanonicalIdentifier[] hTable = Identifier.HashTable;
+ int n = hTable.Length;
+ int n2 = n * 2;
+ CanonicalIdentifier[] newhTable = new CanonicalIdentifier[n2];
+ for (int i = 0; i < n; i++)
+ {
+ CanonicalIdentifier id = hTable[i];
+ if (id.Name == null) continue;
+ int j = id.HashCode % n2;
+ CanonicalIdentifier id2 = newhTable[j];
+ while (id2.Name != null)
+ {
+ j = (j + 1) % n2;
+ id2 = newhTable[j];
+ }
+ newhTable[j] = id;
+ }
+ Identifier.HashTable = newhTable;
+ }
+ public override string/*!*/ ToString()
+ {
+#if !MinimalReader
+ if (this.Prefix != null)
+ return this.Prefix.Name + ":" + this.Name;
+#endif
+ if (this.Name == null) return "";
+ return this.Name;
+ }
+ private int uniqueIdKey;
+ /// <summary>
+ /// Returns an integer that is the same for every Identifier instance that has the same string value, and that is different from
+ /// every other identifier instance that has a different string value. Useful for efficient equality tests when hashing identifiers.
+ /// </summary>
+ public int UniqueIdKey
+ {
+ get
+ {
+ int result = this.uniqueIdKey;
+ if (result != 0) return result;
+ return this.uniqueIdKey = this.GetUniqueIdKey();
+ }
+ }
+ [Obsolete("Use Identifier.UniqueIdKey instead")]
+ public new int UniqueKey
+ {
+ get
+ {
+ int result = this.uniqueIdKey;
+ if (result != 0) return result;
+ return this.uniqueIdKey = this.GetUniqueIdKey();
+ }
+ }
+ }
+#if !MinimalReader
+ public class QualifiedIdentifier : Expression
+ {
+ public Identifier Identifier;
+ public Expression Qualifier;
+ public Expression BoundMember;
+ public bool QualifierIsNamespace;
+
+ public QualifiedIdentifier()
+ : base(NodeType.QualifiedIdentifer)
+ {
+ }
+ public QualifiedIdentifier(Expression qualifier, Identifier identifier)
+ : base(NodeType.QualifiedIdentifer)
+ {
+ this.Identifier = identifier;
+ this.Qualifier = qualifier;
+ }
+ public QualifiedIdentifier(Expression qualifier, Identifier identifier, SourceContext sourceContext)
+ : base(NodeType.QualifiedIdentifer)
+ {
+ this.Identifier = identifier;
+ this.Qualifier = qualifier;
+ this.SourceContext = sourceContext;
+ }
+ public QualifiedIdentifier(Expression qualifier, Identifier identifier, SourceContext sourceContext, bool qualifierIsNamespace)
+ : base(NodeType.QualifiedIdentifer)
+ {
+ this.Identifier = identifier;
+ this.Qualifier = qualifier;
+ this.SourceContext = sourceContext;
+ this.QualifierIsNamespace = qualifierIsNamespace;
+ }
+ public override string/*!*/ ToString()
+ {
+ string str = this.Identifier == null ? "" : this.Identifier.ToString();
+ if (this.Qualifier == null) return str;
+ string separator = this.QualifierIsNamespace ? "::" : "+";
+ return this.Qualifier.ToString() + separator + str;
+ }
+ }
+ public class Quantifier : Expression
+ {
+ public NodeType QuantifierType;
+ public TypeNode SourceType; // the type of elements the quantifier consumes
+ public Comprehension Comprehension;
+ public Quantifier()
+ : base(NodeType.Quantifier)
+ {
+ }
+ public Quantifier(Comprehension comprehension)
+ : base(NodeType.Quantifier)
+ {
+ this.Comprehension = comprehension;
+ }
+ public Quantifier(NodeType t, Comprehension comprehension)
+ : base(NodeType.Quantifier)
+ {
+ this.QuantifierType = t;
+ this.Comprehension = comprehension;
+ }
+ }
+ public enum ComprehensionBindingMode { In, Gets };
+ public class ComprehensionBinding : Expression
+ {
+ public ComprehensionBindingMode Mode = ComprehensionBindingMode.In;
+ public TypeNode TargetVariableType;
+ public TypeNode TargetVariableTypeExpression;
+ public Expression TargetVariable;
+
+ public TypeNode AsTargetVariableType;
+ public TypeNode AsTargetVariableTypeExpression;
+
+ public Expression SourceEnumerable;
+ public BlockScope ScopeForTemporaryVariables;
+ public ComprehensionBinding()
+ : base(NodeType.ComprehensionBinding)
+ {
+ }
+ }
+ public enum ComprehensionMode { Reduction, Comprehension };
+ // {1,2,3} ==> Comprehension with BindingsAndFilters = null and Elements = [1,2,3]
+ // i.e., for a "display", there are no bindings and the elements have one entry per value in the comprehension
+ // { int x in A, P(x); T(x); default } ==> Comprehension with BindingsAndFilters = [int x in A, P(x)] and Elements = [T(x), default]
+ // i.e., for "true" comprehensions, the list of elements will always have either one or two elements (two if there is a default)
+ public class Comprehension : Expression
+ {
+ public ComprehensionMode Mode = ComprehensionMode.Comprehension;
+ public ExpressionList BindingsAndFilters;
+ public ExpressionList Elements;
+
+ public Node nonEnumerableTypeCtor; // used only when the comprehension should generate code for an IList, e.g.
+ public Method AddMethod; // used only when the comprehension should generate code for an IList, e.g.
+ public TypeNode TemporaryHackToHoldType;
+
+ public Comprehension()
+ : base(NodeType.Comprehension)
+ {
+ }
+
+ public bool IsDisplay
+ {
+ get
+ {
+ return this.BindingsAndFilters == null;
+ }
+ }
+ }
+ public class NameBinding : Expression
+ {
+ public Identifier Identifier;
+ public MemberList BoundMembers;
+ public Expression BoundMember;
+ public int LexLevel;
+ public Class MostNestedScope;
+ public NameBinding()
+ : base(NodeType.NameBinding)
+ {
+ }
+ public NameBinding(Identifier identifier, MemberList boundMembers)
+ : base(NodeType.NameBinding)
+ {
+ this.Identifier = identifier;
+ this.BoundMembers = boundMembers;
+ }
+ public NameBinding(Identifier identifier, MemberList boundMembers, SourceContext sctx)
+ : base(NodeType.NameBinding)
+ {
+ this.Identifier = identifier;
+ this.BoundMembers = boundMembers;
+ this.SourceContext = sctx;
+ }
+ public NameBinding(Identifier identifier, MemberList boundMembers, Class mostNestedScope, int lexLevel)
+ : base(NodeType.NameBinding)
+ {
+ this.Identifier = identifier;
+ this.BoundMembers = boundMembers;
+ this.LexLevel = lexLevel;
+ this.MostNestedScope = mostNestedScope;
+ }
+ public NameBinding(Identifier identifier, MemberList boundMembers, Class mostNestedScope, int lexLevel, SourceContext sctx)
+ : base(NodeType.NameBinding)
+ {
+ this.Identifier = identifier;
+ this.BoundMembers = boundMembers;
+ this.LexLevel = lexLevel;
+ this.MostNestedScope = mostNestedScope;
+ this.SourceContext = sctx;
+ }
+ public override string ToString()
+ {
+ return this.Identifier == null ? "" : this.Identifier.ToString();
+ }
+ }
+ public class TemplateInstance : Expression
+ {
+ public Expression Expression;
+ public TypeNodeList TypeArguments;
+ public TypeNodeList TypeArgumentExpressions;
+ public bool IsMethodTemplate;
+ public MemberList BoundMembers;
+
+ public TemplateInstance()
+ : this(null, null)
+ {
+ }
+ public TemplateInstance(Expression expression, TypeNodeList typeArguments)
+ : base(NodeType.TemplateInstance)
+ {
+ this.Expression = expression;
+ this.TypeArguments = typeArguments;
+ }
+ }
+ public class StackAlloc : Expression
+ {
+ public TypeNode ElementType;
+ public TypeNode ElementTypeExpression;
+ public Expression NumberOfElements;
+
+ public StackAlloc()
+ : base(NodeType.StackAlloc)
+ {
+ }
+ public StackAlloc(TypeNode elementType, Expression numberOfElements, SourceContext sctx)
+ : base(NodeType.StackAlloc)
+ {
+ this.ElementType = this.ElementTypeExpression = elementType;
+ this.NumberOfElements = numberOfElements;
+ this.SourceContext = sctx;
+ }
+ }
+#endif
+ public class MethodCall : NaryExpression
+ {
+ private Expression callee;
+ private TypeNode constraint;
+ private bool isTailCall;
+#if !MinimalReader
+ public Expression CalleeExpression;
+ public bool GiveErrorIfSpecialNameMethod;
+ public bool ArgumentListIsIncomplete;
+ public MethodCall()
+ {
+ this.NodeType = NodeType.MethodCall;
+ }
+ public MethodCall(Expression callee, ExpressionList arguments)
+ : base(arguments, NodeType.MethodCall)
+ {
+ this.callee = this.CalleeExpression = callee;
+ this.isTailCall = false;
+ }
+#endif
+ public MethodCall(Expression callee, ExpressionList arguments, NodeType typeOfCall)
+ : base(arguments, typeOfCall)
+ {
+ this.callee = callee;
+#if !MinimalReader
+ this.CalleeExpression = callee;
+#endif
+ //this.isTailCall = false;
+ }
+#if !MinimalReader
+ public MethodCall(Expression callee, ExpressionList arguments, NodeType typeOfCall, TypeNode resultType)
+ : this(callee, arguments, typeOfCall)
+ {
+ this.Type = resultType;
+ }
+ public MethodCall(Expression callee, ExpressionList arguments, NodeType typeOfCall, TypeNode resultType, SourceContext sctx)
+ : this(callee, arguments, typeOfCall, resultType)
+ {
+ this.SourceContext = sctx;
+ }
+#endif
+ public Expression Callee
+ {
+ get { return this.callee; }
+ set { this.callee = value; }
+ }
+ public bool IsTailCall
+ {
+ get { return this.isTailCall; }
+ set { this.isTailCall = value; }
+ }
+ public TypeNode Constraint
+ {
+ get { return this.constraint; }
+ set { this.constraint = value; }
+ }
+ }
+ public class Construct : NaryExpression
+ {
+ private Expression constructor;
+#if !MinimalReader
+ public Expression Owner;
+#endif
+ public Construct()
+ {
+ this.NodeType = NodeType.Construct;
+ }
+ public Construct(Expression constructor, ExpressionList arguments)
+ : base(arguments, NodeType.Construct)
+ {
+ this.constructor = constructor;
+ }
+#if !MinimalReader
+ public Construct(Expression constructor, ExpressionList arguments, SourceContext sctx)
+ : base(arguments, NodeType.Construct)
+ {
+ this.constructor = constructor;
+ this.SourceContext = sctx;
+ }
+ public Construct(Expression constructor, ExpressionList arguments, TypeNode type)
+ : base(arguments, NodeType.Construct)
+ {
+ this.constructor = constructor;
+ this.Type = type;
+ }
+ public Construct(Expression constructor, ExpressionList arguments, TypeNode type, SourceContext sctx)
+ : base(arguments, NodeType.Construct)
+ {
+ this.constructor = constructor;
+ this.Type = type;
+ this.SourceContext = sctx;
+ }
+#endif
+ public Expression Constructor
+ {
+ get { return this.constructor; }
+ set { this.constructor = value; }
+ }
+ }
+ public class ConstructArray : NaryExpression
+ {
+ private TypeNode elementType;
+ private int rank;
+#if !MinimalReader
+ public TypeNode ElementTypeExpression;
+ public ExpressionList Initializers;
+ public Expression Owner;
+#endif
+ public ConstructArray()
+ {
+ this.NodeType = NodeType.ConstructArray;
+ this.rank = 1;
+ }
+ public ConstructArray(TypeNode elementType, ExpressionList sizes, ExpressionList initializers)
+ : base(sizes, NodeType.ConstructArray)
+ {
+ this.elementType = elementType;
+ this.Operands = sizes;
+ this.rank = sizes == null ? 1 : sizes.Count;
+#if !MinimalReader
+ this.Initializers = initializers;
+#endif
+ }
+#if !MinimalReader
+ public ConstructArray(TypeNode elementType, ExpressionList initializers)
+ : base(null, NodeType.ConstructArray)
+ {
+ this.elementType = elementType;
+ this.Initializers = initializers;
+ this.rank = 1;
+ if (elementType != null)
+ this.Type = elementType.GetArrayType(1);
+ }
+ public ConstructArray(TypeNode elementType, int rank, ExpressionList initializers)
+ : base(null, NodeType.ConstructArray)
+ {
+ this.elementType = elementType;
+ this.Initializers = initializers;
+ this.rank = rank;
+ if (elementType != null)
+ this.Type = elementType.GetArrayType(1);
+ }
+#endif
+ public TypeNode ElementType
+ {
+ get { return this.elementType; }
+ set { this.elementType = value; }
+ }
+ public int Rank
+ {
+ get { return this.rank; }
+ set { this.rank = value; }
+ }
+ }
+#if !MinimalReader
+ public class ConstructFlexArray : NaryExpression
+ {
+ public TypeNode ElementType;
+ public TypeNode ElementTypeExpression;
+ public ExpressionList Initializers;
+ public ConstructFlexArray()
+ {
+ this.NodeType = NodeType.ConstructFlexArray;
+ }
+ public ConstructFlexArray(TypeNode elementType, ExpressionList sizes, ExpressionList initializers)
+ : base(sizes, NodeType.ConstructFlexArray)
+ {
+ this.ElementType = elementType;
+ this.Operands = sizes;
+ this.Initializers = initializers;
+ }
+ }
+ public class ConstructDelegate : Expression
+ {
+ public TypeNode DelegateType;
+ public TypeNode DelegateTypeExpression;
+ public Identifier MethodName;
+ public Expression TargetObject;
+ public ConstructDelegate()
+ : base(NodeType.ConstructDelegate)
+ {
+ }
+ public ConstructDelegate(TypeNode delegateType, Expression targetObject, Identifier methodName)
+ : base(NodeType.ConstructDelegate)
+ {
+ this.DelegateType = delegateType;
+ this.MethodName = methodName;
+ this.TargetObject = targetObject;
+ }
+ public ConstructDelegate(TypeNode delegateType, Expression targetObject, Identifier methodName, SourceContext sctx)
+ : base(NodeType.ConstructDelegate)
+ {
+ this.DelegateType = delegateType;
+ this.MethodName = methodName;
+ this.TargetObject = targetObject;
+ this.SourceContext = sctx;
+ }
+ }
+ public class ConstructIterator : Expression
+ {
+ public Class State;
+ public Block Body;
+ public TypeNode ElementType;
+ public ConstructIterator()
+ : base(NodeType.ConstructIterator)
+ {
+ }
+ public ConstructIterator(Class state, Block body, TypeNode elementType, TypeNode type)
+ : base(NodeType.ConstructIterator)
+ {
+ this.State = state;
+ this.Body = body;
+ this.ElementType = elementType;
+ this.Type = type;
+ }
+ }
+ public class ConstructTuple : Expression
+ {
+ public FieldList Fields;
+ public ConstructTuple()
+ : base(NodeType.ConstructTuple)
+ {
+ }
+ }
+ public class CoerceTuple : ConstructTuple
+ {
+ public Expression OriginalTuple;
+ public Local Temp;
+ public CoerceTuple()
+ {
+ this.NodeType = NodeType.CoerceTuple;
+ }
+ }
+#endif
+ public class Indexer : NaryExpression
+ {
+#if !MinimalReader
+ public Property CorrespondingDefaultIndexedProperty;
+ public bool ArgumentListIsIncomplete;
+#endif
+ public Indexer()
+ {
+ this.NodeType = NodeType.Indexer;
+ }
+ public Indexer(Expression @object, ExpressionList arguments)
+ : base(arguments, NodeType.Indexer)
+ {
+ this.@object = @object;
+ }
+#if !MinimalReader
+ public Indexer(Expression Object, ExpressionList arguments, SourceContext sctx)
+ : base(arguments, NodeType.Indexer)
+ {
+ this.@object = Object;
+ this.SourceContext = sctx;
+ }
+ public Indexer(Expression Object, ExpressionList arguments, TypeNode elementType)
+ : base(arguments, NodeType.Indexer)
+ {
+ this.@object = Object;
+ this.elementType = this.Type = elementType;
+ }
+ public Indexer(Expression Object, ExpressionList arguments, TypeNode elementType, SourceContext sctx)
+ : base(arguments, NodeType.Indexer)
+ {
+ this.@object = Object;
+ this.elementType = this.Type = elementType;
+ this.SourceContext = sctx;
+ }
+#endif
+ private Expression @object;
+ public Expression Object
+ {
+ get { return this.@object; }
+ set { this.@object = value; }
+ }
+ private TypeNode elementType;
+ /// <summary>
+ /// This type is normally expected to be the same the value of Type. However, if the indexer applies to an array of enums, then
+ /// Type will be the enum type and ElementType will be the underlying type of the enum.
+ /// </summary>
+ public TypeNode ElementType
+ {
+ get { return this.elementType; }
+ set { this.elementType = value; }
+ }
+ }
+#if !MinimalReader
+ public class CollectionEnumerator : Expression
+ {
+ public Expression Collection;
+ public Method DefaultIndexerGetter;
+ public Method LengthPropertyGetter;
+ public Method GetEnumerator;
+ public Method MoveNext;
+ public Method GetCurrent;
+ public Local ElementLocal;
+ public Expression ElementCoercion;
+ public CollectionEnumerator()
+ : base(NodeType.CollectionEnumerator)
+ {
+ }
+ }
+ /// <summary>
+ /// 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).
+ /// </summary>
+ public class LRExpression : Expression
+ {
+ public Expression Expression;
+ public LocalList Temporaries;
+ public ExpressionList SubexpressionsToEvaluateOnce;
+ public LRExpression(Expression/*!*/ expression)
+ : base(NodeType.LRExpression)
+ {
+ this.Expression = expression;
+ this.Type = expression.Type;
+ }
+ }
+ public class AssignmentExpression : Expression
+ {
+ public Statement AssignmentStatement;
+ public AssignmentExpression()
+ : base(NodeType.AssignmentExpression)
+ {
+ }
+ public AssignmentExpression(AssignmentStatement assignment)
+ : base(NodeType.AssignmentExpression)
+ {
+ this.AssignmentStatement = assignment;
+ }
+ }
+#endif
+#if !MinimalReader || FxCop
+ public class BlockExpression : Expression
+ {
+ public Block Block;
+ public BlockExpression()
+ : base(NodeType.BlockExpression)
+ {
+ }
+ public BlockExpression(Block block)
+ : base(NodeType.BlockExpression)
+ {
+ this.Block = block;
+ }
+ public BlockExpression(Block block, TypeNode type)
+ : base(NodeType.BlockExpression)
+ {
+ this.Block = block;
+ this.Type = type;
+ }
+ public BlockExpression(Block block, TypeNode type, SourceContext sctx)
+ : base(NodeType.BlockExpression)
+ {
+ this.Block = block;
+ this.Type = type;
+ this.SourceContext = sctx;
+ }
+ }
+#endif
+#if !MinimalReader
+ public class AnonymousNestedFunction : Expression
+ {
+ public ParameterList Parameters;
+ public Block Body;
+ public Method Method;
+ public Expression Invocation;
+
+ public AnonymousNestedFunction()
+ : base(NodeType.AnonymousNestedFunction)
+ {
+ }
+ public AnonymousNestedFunction(ParameterList parameters, Block body)
+ : base(NodeType.AnonymousNestedFunction)
+ {
+ this.Parameters = parameters;
+ this.Body = body;
+ }
+ public AnonymousNestedFunction(ParameterList parameters, Block body, SourceContext sctx)
+ : base(NodeType.AnonymousNestedFunction)
+ {
+ this.Parameters = parameters;
+ this.Body = body;
+ this.SourceContext = sctx;
+ }
+ }
+#endif
+ public class Instruction : Node
+ {
+ private OpCode opCode;
+ private int offset;
+ private object value;
+ public Instruction()
+ : base(NodeType.Instruction)
+ {
+ }
+ public Instruction(OpCode opCode, int offset)
+ : this(opCode, offset, null)
+ {
+ }
+ public Instruction(OpCode opCode, int offset, object value)
+ : base(NodeType.Instruction)
+ {
+ this.opCode = opCode;
+ this.offset = offset;
+ this.value = value;
+ }
+ /// <summary>The actual value of the opcode</summary>
+ public OpCode OpCode
+ {
+ get { return this.opCode; }
+ set { this.opCode = value; }
+ }
+ /// <summary>The offset from the start of the instruction stream of a method</summary>
+ public int Offset
+ {
+ get { return this.offset; }
+ set { this.offset = value; }
+ }
+ /// <summary>Immediate data such as a string, the address of a branch target, or a metadata reference, such as a Field</summary>
+ public object Value
+ {
+ get { return this.value; }
+ set { this.value = value; }
+ }
+ }
+ public class Statement : Node
+ {
+#if FxCop
+ internal int ILOffset;
+#endif
+ public Statement(NodeType nodeType)
+ : base(nodeType)
+ {
+ }
+#if !MinimalReader
+ public Statement(NodeType nodeType, SourceContext sctx)
+ : base(nodeType)
+ {
+ this.SourceContext = sctx;
+ }
+#endif
+ }
+ public class Block : Statement
+ {
+ private StatementList statements;
+#if !MinimalReader
+ public bool Checked;
+ public bool SuppressCheck;
+#endif
+#if !MinimalReader || !NoWriter
+ public bool HasLocals;
+#endif
+#if !MinimalReader
+ public bool IsUnsafe;
+ public BlockScope Scope;
+#endif
+ public Block()
+ : base(NodeType.Block)
+ {
+ }
+ public Block(StatementList statements)
+ : base(NodeType.Block)
+ {
+ this.statements = statements;
+ }
+#if !MinimalReader
+ public Block(StatementList statements, SourceContext sourceContext)
+ : base(NodeType.Block)
+ {
+ this.SourceContext = sourceContext;
+ this.statements = statements;
+ }
+ public Block(StatementList statements, bool Checked, bool SuppressCheck, bool IsUnsafe)
+ : base(NodeType.Block)
+ {
+ this.Checked = Checked;
+ this.IsUnsafe = IsUnsafe;
+ this.SuppressCheck = SuppressCheck;
+ this.statements = statements;
+ }
+ public Block(StatementList statements, SourceContext sourceContext, bool Checked, bool SuppressCheck, bool IsUnsafe)
+ : base(NodeType.Block)
+ {
+ this.Checked = Checked;
+ this.IsUnsafe = IsUnsafe;
+ this.SuppressCheck = SuppressCheck;
+ this.SourceContext = sourceContext;
+ this.statements = statements;
+ }
+ public override string ToString()
+ {
+ return "B#" + this.UniqueKey.ToString();
+ }
+#endif
+ public StatementList Statements
+ {
+ get { return this.statements; }
+ set { this.statements = value; }
+ }
+ }
+#if !MinimalReader
+ public class LabeledStatement : Block
+ {
+ public Identifier Label;
+ public Statement Statement;
+ public LabeledStatement()
+ {
+ this.NodeType = NodeType.LabeledStatement;
+ }
+ }
+ public class FunctionDeclaration : Statement
+ {
+ public Identifier Name;
+ public ParameterList Parameters;
+ public TypeNode ReturnType;
+ public TypeNode ReturnTypeExpression;
+ public Block Body;
+ public Method Method;
+
+ public FunctionDeclaration()
+ : base(NodeType.FunctionDeclaration)
+ {
+ }
+ public FunctionDeclaration(Identifier name, ParameterList parameters, TypeNode returnType, Block body)
+ : base(NodeType.FunctionDeclaration)
+ {
+ this.Name = name;
+ this.Parameters = parameters;
+ this.ReturnType = returnType;
+ this.Body = body;
+ }
+ }
+ public class Assertion : Statement
+ {
+ public Expression Condition;
+ public Assertion()
+ : base(NodeType.Assertion)
+ {
+ }
+ public Assertion(Expression condition)
+ : base(NodeType.Assertion)
+ {
+ this.Condition = condition;
+ }
+ }
+ public class Assumption : Statement
+ {
+ public Expression Condition;
+ public Assumption()
+ : base(NodeType.Assumption)
+ {
+ }
+ public Assumption(Expression condition)
+ : base(NodeType.Assumption)
+ {
+ this.Condition = condition;
+ }
+ }
+#endif
+ public class AssignmentStatement : Statement
+ {
+ private NodeType @operator;
+ private Expression source;
+ private Expression target;
+#if !MinimalReader
+ public Method OperatorOverload;
+ ///<summary>A Type two which both operands must be coerced before carrying out the operation (if any).</summary>
+ public TypeNode UnifiedType;
+#endif
+ public AssignmentStatement()
+ : base(NodeType.AssignmentStatement)
+ {
+ this.Operator = NodeType.Nop;
+ }
+ public AssignmentStatement(Expression target, Expression source)
+ : this(target, source, NodeType.Nop)
+ {
+ }
+#if !MinimalReader
+ public AssignmentStatement(Expression target, Expression source, SourceContext context)
+ : this(target, source, NodeType.Nop)
+ {
+ this.SourceContext = context;
+ }
+#endif
+ public AssignmentStatement(Expression target, Expression source, NodeType @operator)
+ : base(NodeType.AssignmentStatement)
+ {
+ this.target = target;
+ this.source = source;
+ this.@operator = @operator;
+ }
+#if !MinimalReader
+ public AssignmentStatement(Expression target, Expression source, NodeType Operator, SourceContext context)
+ : this(target, source, Operator)
+ {
+ this.SourceContext = context;
+ }
+#endif
+ public NodeType Operator
+ {
+ get { return this.@operator; }
+ set { this.@operator = value; }
+ }
+ public Expression Source
+ {
+ get { return this.source; }
+ set { this.source = value; }
+ }
+ public Expression Target
+ {
+ get { return this.target; }
+ set { this.target = value; }
+ }
+ }
+ public class ExpressionStatement : Statement
+ {
+ private Expression expression;
+ public ExpressionStatement()
+ : base(NodeType.ExpressionStatement)
+ {
+ }
+ public ExpressionStatement(Expression expression)
+ : base(NodeType.ExpressionStatement)
+ {
+ this.Expression = expression;
+ }
+#if !MinimalReader
+ public ExpressionStatement(Expression expression, SourceContext sctx)
+ : base(NodeType.ExpressionStatement)
+ {
+ this.Expression = expression;
+ this.SourceContext = sctx;
+ }
+#endif
+ public Expression Expression
+ {
+ get { return this.expression; }
+ set { this.expression = value; }
+ }
+ }
+ public class Branch : Statement
+ {
+ private Expression condition;
+ private bool leavesExceptionBlock;
+ internal bool shortOffset;
+ private Block target;
+ public bool BranchIfUnordered;
+ public Branch()
+ : base(NodeType.Branch)
+ {
+ }
+#if !MinimalReader
+ public Branch(Expression condition, Block target)
+ : this(condition, target, false, false, false)
+ {
+ }
+ public Branch(Expression condition, Block target, SourceContext sourceContext)
+ : this(condition, target, false, false, false)
+ {
+ this.SourceContext = sourceContext;
+ }
+ public Branch(Expression condition, Block target, SourceContext sourceContext, bool unordered)
+ : this(condition, target, false, false, false)
+ {
+ this.BranchIfUnordered = unordered;
+ this.SourceContext = sourceContext;
+ }
+#endif
+ public Branch(Expression condition, Block target, bool shortOffset, bool unordered, bool leavesExceptionBlock)
+ : base(NodeType.Branch)
+ {
+ this.BranchIfUnordered = unordered;
+ this.condition = condition;
+ this.leavesExceptionBlock = leavesExceptionBlock;
+ this.shortOffset = shortOffset;
+ this.target = target;
+ }
+ public Expression Condition
+ {
+ get { return this.condition; }
+ set { this.condition = value; }
+ }
+ public bool LeavesExceptionBlock
+ {
+ get { return this.leavesExceptionBlock; }
+ set { this.leavesExceptionBlock = value; }
+ }
+ public bool ShortOffset
+ {
+ get { return this.shortOffset; }
+ set { this.shortOffset = value; }
+ }
+ public Block Target
+ {
+ get { return this.target; }
+ set { this.target = value; }
+ }
+ }
+#if FxCop
+ public class ReturnNode : ExpressionStatement{
+ public ReturnNode()
+#else
+ public class Return : ExpressionStatement
+ {
+ public Return()
+#endif
+ : base()
+ {
+ this.NodeType = NodeType.Return;
+ }
+#if FxCop
+ public ReturnNode(Expression expression)
+#else
+ public Return(Expression expression)
+#endif
+ : base(expression)
+ {
+ this.NodeType = NodeType.Return;
+ }
+#if !MinimalReader
+ public Return(SourceContext sctx)
+ : base()
+ {
+ this.NodeType = NodeType.Return;
+ this.SourceContext = sctx;
+ }
+ public Return(Expression expression, SourceContext sctx)
+ : base(expression)
+ {
+ this.NodeType = NodeType.Return;
+ this.SourceContext = sctx;
+ }
+#endif
+ }
+#if !MinimalReader
+ public class Yield : ExpressionStatement
+ {
+ public Yield()
+ : base()
+ {
+ this.NodeType = NodeType.Yield;
+ }
+ public Yield(Expression expression)
+ : base(expression)
+ {
+ this.NodeType = NodeType.Yield;
+ }
+ public Yield(Expression expression, SourceContext sctx)
+ : base(expression)
+ {
+ this.NodeType = NodeType.Yield;
+ this.SourceContext = sctx;
+ }
+ }
+ public class Try : Statement
+ {
+ private CatchList catchers;
+ private FilterList filters;
+ private FaultHandlerList faultHandlers;
+ private Finally finallyClause;
+ private Block tryBlock;
+ public Try()
+ : base(NodeType.Try)
+ {
+ }
+ public Try(Block tryBlock, CatchList catchers, FilterList filters, FaultHandlerList faultHandlers, Finally Finally)
+ : base(NodeType.Try)
+ {
+ this.catchers = catchers;
+ this.faultHandlers = faultHandlers;
+ this.filters = filters;
+ this.finallyClause = Finally;
+ this.tryBlock = tryBlock;
+ }
+ public CatchList Catchers
+ {
+ get { return this.catchers; }
+ set { this.catchers = value; }
+ }
+ public FilterList Filters
+ {
+ get { return this.filters; }
+ set { this.filters = value; }
+ }
+ public FaultHandlerList FaultHandlers
+ {
+ get { return this.faultHandlers; }
+ set { this.faultHandlers = value; }
+ }
+ public Finally Finally
+ {
+ get { return this.finallyClause; }
+ set { this.finallyClause = value; }
+ }
+ public Block TryBlock
+ {
+ get { return this.tryBlock; }
+ set { this.tryBlock = value; }
+ }
+ }
+ public class Catch : Statement
+ {
+ private Block block;
+ private TypeNode type;
+ private Expression variable;
+ public TypeNode TypeExpression;
+ public Catch()
+ : base(NodeType.Catch)
+ {
+ }
+ public Catch(Block block, Expression variable, TypeNode type)
+ : base(NodeType.Catch)
+ {
+ this.block = block;
+ this.variable = variable;
+ this.type = type;
+ }
+ public Block Block
+ {
+ get { return this.block; }
+ set { this.block = value; }
+ }
+ public TypeNode Type
+ {
+ get { return this.type; }
+ set { this.type = value; }
+ }
+ public Expression Variable
+ {
+ get { return this.variable; }
+ set { this.variable = value; }
+ }
+ }
+ public class Finally : Statement
+ {
+ private Block block;
+ public Finally()
+ : base(NodeType.Finally)
+ {
+ }
+ public Finally(Block block)
+ : base(NodeType.Finally)
+ {
+ this.block = block;
+ }
+ public Block Block
+ {
+ get { return this.block; }
+ set { this.block = value; }
+ }
+ }
+#endif
+ public class EndFinally : Statement
+ {
+ public EndFinally()
+ : base(NodeType.EndFinally)
+ {
+ }
+ }
+#if !MinimalReader || FxCop
+ public class Filter : Statement
+ {
+ private Block block;
+ private Expression expression;
+#if FxCop
+ internal int handlerEnd;
+#endif
+ public Filter()
+ : base(NodeType.Filter)
+ {
+ }
+ public Filter(Block block, Expression expression)
+ : base(NodeType.Filter)
+ {
+ this.block = block;
+ this.expression = expression;
+ }
+ public Block Block
+ {
+ get { return this.block; }
+ set { this.block = value; }
+ }
+ public Expression Expression
+ {
+ get { return this.expression; }
+ set { this.expression = value; }
+ }
+ }
+#endif
+ public class EndFilter : Statement
+ {
+ private Expression value;
+ public EndFilter()
+ : base(NodeType.EndFilter)
+ {
+ }
+ public EndFilter(Expression value)
+ : base(NodeType.EndFilter)
+ {
+ this.value = value;
+ }
+ public Expression Value
+ {
+ get { return this.value; }
+ set { this.value = value; }
+ }
+ }
+#if !MinimalReader || FxCop
+ public class FaultHandler : Statement
+ {
+ private Block block;
+#if FxCop
+ internal int handlerEnd;
+#endif
+ public FaultHandler()
+ : base(NodeType.FaultHandler)
+ {
+ }
+ public FaultHandler(Block block)
+ : base(NodeType.FaultHandler)
+ {
+ this.block = block;
+ }
+ public Block Block
+ {
+ get { return this.block; }
+ set { this.block = value; }
+ }
+ }
+#endif
+#if FxCop
+ public class ThrowNode : Statement{
+#else
+ public class Throw : Statement
+ {
+#endif
+ private Expression expression;
+#if FxCop
+ public ThrowNode()
+ : base(NodeType.Throw){
+ }
+ public ThrowNode(Expression expression)
+ : base(NodeType.Throw){
+ this.expression = expression;
+ }
+#else
+ public Throw()
+ : base(NodeType.Throw)
+ {
+ }
+ public Throw(Expression expression)
+ : base(NodeType.Throw)
+ {
+ this.expression = expression;
+ }
+#endif
+#if !MinimalReader
+ public Throw(Expression expression, SourceContext context)
+ : base(NodeType.Throw)
+ {
+ this.expression = expression;
+ this.SourceContext = context;
+ }
+#endif
+ public Expression Expression
+ {
+ get { return this.expression; }
+ set { this.expression = value; }
+ }
+ }
+#if !MinimalReader
+ public class If : Statement
+ {
+ public Expression Condition;
+ public Block TrueBlock;
+ public Block FalseBlock;
+ public SourceContext ConditionContext;
+ public SourceContext ElseContext;
+ public SourceContext EndIfContext;
+ public If()
+ : base(NodeType.If)
+ {
+ }
+ public If(Expression condition, Block trueBlock, Block falseBlock)
+ : base(NodeType.If)
+ {
+ this.Condition = condition;
+ if (condition != null)
+ this.ConditionContext = condition.SourceContext;
+ this.TrueBlock = trueBlock;
+ this.FalseBlock = falseBlock;
+ }
+ }
+ public class For : Statement
+ {
+ public Block Body;
+ public Expression Condition;
+ public StatementList Incrementer;
+ public StatementList Initializer;
+ public ExpressionList Invariants;
+ public For()
+ : base(NodeType.For)
+ {
+ }
+ public For(StatementList initializer, Expression condition, StatementList incrementer, Block body)
+ : base(NodeType.For)
+ {
+ this.Body = body;
+ this.Condition = condition;
+ this.Incrementer = incrementer;
+ this.Initializer = initializer;
+ }
+ }
+ public class ForEach : Statement
+ {
+ public Block Body;
+ public Expression SourceEnumerable;
+ public BlockScope ScopeForTemporaryVariables;
+ public Expression TargetVariable;
+ public TypeNode TargetVariableType;
+ public TypeNode TargetVariableTypeExpression;
+ public Expression InductionVariable;
+ public ExpressionList Invariants;
+ public bool StatementTerminatesNormallyIfEnumerableIsNull = true;
+ public bool StatementTerminatesNormallyIfEnumeratorIsNull = true;
+ public ForEach()
+ : base(NodeType.ForEach)
+ {
+ }
+ public ForEach(TypeNode targetVariableType, Expression targetVariable, Expression sourceEnumerable, Block body)
+ : base(NodeType.ForEach)
+ {
+ this.TargetVariable = targetVariable;
+ this.TargetVariableType = targetVariableType;
+ this.SourceEnumerable = sourceEnumerable;
+ this.Body = body;
+ }
+ }
+ public class Exit : Statement
+ {
+ public Literal Level;
+ public Exit()
+ : base(NodeType.Exit)
+ {
+ }
+ public Exit(Literal level)
+ : base(NodeType.Exit)
+ {
+ this.Level = level;
+ }
+ }
+ public class Continue : Statement
+ {
+ public Literal Level;
+ public Continue()
+ : base(NodeType.Continue)
+ {
+ }
+ public Continue(Literal level)
+ : base(NodeType.Continue)
+ {
+ this.Level = level;
+ }
+ }
+ public class Switch : Statement
+ {
+ public SwitchCaseList Cases;
+ public Expression Expression;
+ public Local Nullable;
+ public Expression NullableExpression;
+ public BlockScope Scope;
+ public Switch()
+ : base(NodeType.Switch)
+ {
+ }
+ public Switch(Expression expression, SwitchCaseList cases)
+ : base(NodeType.Switch)
+ {
+ this.Cases = cases;
+ this.Expression = expression;
+ }
+ }
+ public class SwitchCase : Node
+ {
+ public Block Body;
+ public Expression Label;
+ public SwitchCase()
+ : base(NodeType.SwitchCase)
+ {
+ }
+ public SwitchCase(Expression label, Block body)
+ : base(NodeType.SwitchCase)
+ {
+ this.Body = body;
+ this.Label = label;
+ }
+ }
+ public class GotoCase : Statement
+ {
+ public Expression CaseLabel;
+ public GotoCase(Expression caseLabel)
+ : base(NodeType.GotoCase)
+ {
+ this.CaseLabel = caseLabel;
+ }
+ }
+#endif
+ public class SwitchInstruction : Statement
+ {
+ private Expression expression;
+ private BlockList targets;
+ public SwitchInstruction()
+ : base(NodeType.SwitchInstruction)
+ {
+ }
+ public SwitchInstruction(Expression expression, BlockList targets)
+ : base(NodeType.SwitchInstruction)
+ {
+ this.expression = expression;
+ this.targets = targets;
+ }
+ public Expression Expression
+ {
+ get { return this.expression; }
+ set { this.expression = value; }
+ }
+ public BlockList Targets
+ {
+ get { return this.targets; }
+ set { this.targets = value; }
+ }
+ }
+#if !MinimalReader
+ public class Typeswitch : Statement
+ {
+ public TypeswitchCaseList Cases;
+ public Expression Expression;
+ public Typeswitch()
+ : base(NodeType.Typeswitch)
+ {
+ }
+ public Typeswitch(Expression expression, TypeswitchCaseList cases)
+ : base(NodeType.Typeswitch)
+ {
+ this.Cases = cases;
+ this.Expression = expression;
+ }
+ }
+ public class TypeswitchCase : Node
+ {
+ public Block Body;
+ public TypeNode LabelType;
+ public TypeNode LabelTypeExpression;
+ public Expression LabelVariable;
+ public TypeswitchCase()
+ : base(NodeType.TypeswitchCase)
+ {
+ }
+ public TypeswitchCase(TypeNode labelType, Expression labelVariable, Block body)
+ : base(NodeType.TypeswitchCase)
+ {
+ this.Body = body;
+ this.LabelType = labelType;
+ this.LabelVariable = labelVariable;
+ }
+ }
+ public class While : Statement
+ {
+ public Expression Condition;
+ public ExpressionList Invariants;
+ public Block Body;
+ public While()
+ : base(NodeType.While)
+ {
+ }
+ public While(Expression condition, Block body)
+ : base(NodeType.While)
+ {
+ this.Condition = condition;
+ this.Body = body;
+ }
+ }
+ public class DoWhile : Statement
+ {
+ public Expression Condition;
+ public ExpressionList Invariants;
+ public Block Body;
+ public DoWhile()
+ : base(NodeType.DoWhile)
+ {
+ }
+ public DoWhile(Expression condition, Block body)
+ : base(NodeType.DoWhile)
+ {
+ this.Condition = condition;
+ this.Body = body;
+ }
+ }
+ public class Repeat : Statement
+ {
+ public Expression Condition;
+ public Block Body;
+ public Repeat()
+ : base(NodeType.Repeat)
+ {
+ }
+ public Repeat(Expression condition, Block body)
+ : base(NodeType.Repeat)
+ {
+ this.Condition = condition;
+ this.Body = body;
+ }
+ }
+ public class Fixed : Statement
+ {
+ public Statement Declarators;
+ public Block Body;
+ public BlockScope ScopeForTemporaryVariables;
+ public Fixed()
+ : base(NodeType.Fixed)
+ {
+ }
+ }
+ public class Lock : Statement
+ {
+ public Expression Guard;
+ public Block Body;
+ public BlockScope ScopeForTemporaryVariable;
+ public Lock()
+ : base(NodeType.Lock)
+ {
+ }
+ }
+ public class ResourceUse : Statement
+ {
+ public Statement ResourceAcquisition;
+ public Block Body;
+ public BlockScope ScopeForTemporaryVariable;
+ public ResourceUse()
+ : base(NodeType.ResourceUse)
+ {
+ }
+ }
+ public class Goto : Statement
+ {
+ public Identifier TargetLabel;
+ public Goto()
+ : base(NodeType.Goto)
+ {
+ }
+ public Goto(Identifier targetLabel)
+ : base(NodeType.Goto)
+ {
+ this.TargetLabel = targetLabel;
+ }
+ }
+ public class VariableDeclaration : Statement
+ {
+ public Expression Initializer;
+ public Identifier Name;
+ public TypeNode Type;
+ public TypeNode TypeExpression;
+ public Field Field;
+ public VariableDeclaration()
+ : base(NodeType.VariableDeclaration)
+ {
+ }
+ public VariableDeclaration(Identifier name, TypeNode type, Expression initializer)
+ : base(NodeType.VariableDeclaration)
+ {
+ this.Initializer = initializer;
+ this.Name = name;
+ this.Type = type;
+ }
+ }
+ public class LocalDeclaration : Node
+ {
+ public Field Field;
+ public Identifier Name;
+ public Expression InitialValue;
+ /// <summary>
+ /// Used when converting a declaration with initializer into an assignment statement.
+ /// Usually Nop, but could be set to CopyReference to avoid dereferencing on either side.
+ /// </summary>
+ public NodeType AssignmentNodeType = NodeType.Nop;
+ public LocalDeclaration()
+ : base(NodeType.LocalDeclaration)
+ {
+ }
+ public LocalDeclaration(Identifier name, Expression initialValue)
+ : base(NodeType.LocalDeclaration)
+ {
+ this.Name = name;
+ this.InitialValue = initialValue;
+ }
+ public LocalDeclaration(Identifier name, Expression initialValue, NodeType assignmentNodeType)
+ : base(NodeType.LocalDeclaration)
+ {
+ this.Name = name;
+ this.InitialValue = initialValue;
+ this.AssignmentNodeType = assignmentNodeType;
+ }
+
+ }
+ public class LocalDeclarationsStatement : Statement
+ {
+ public bool Constant;
+ public bool InitOnly;
+ public TypeNode Type;
+ public TypeNode TypeExpression;
+ public LocalDeclarationList Declarations;
+ public LocalDeclarationsStatement()
+ : base(NodeType.LocalDeclarationsStatement)
+ {
+ }
+ public LocalDeclarationsStatement(LocalDeclaration ldecl, TypeNode type)
+ : base(NodeType.LocalDeclarationsStatement)
+ {
+ Declarations = new LocalDeclarationList();
+ Declarations.Add(ldecl);
+ this.Type = type;
+ }
+ }
+ public class StatementSnippet : Statement
+ {
+ public IParserFactory ParserFactory;
+
+ public StatementSnippet()
+ : base(NodeType.StatementSnippet)
+ {
+ }
+ public StatementSnippet(IParserFactory parserFactory, SourceContext sctx)
+ : base(NodeType.StatementSnippet)
+ {
+ this.ParserFactory = parserFactory;
+ this.SourceContext = sctx;
+ }
+ }
+ /// <summary>
+ /// Associates an identifier with a type or a namespace or a Uri or a list of assemblies.
+ /// In C# alias identifiers are used as root identifiers in qualified expressions, or as identifier prefixes.
+ /// </summary>
+ public class AliasDefinition : Node
+ {
+
+ /// <summary>The identifier that serves as an alias for the type, namespace, Uri or list of assemblies.</summary>
+ public Identifier Alias;
+
+ /// <summary>The list of assemblies being aliased.</summary>
+ public AssemblyReferenceList AliasedAssemblies;
+
+ /// <summary>The expression that was (or should be) resolved into a type, namespace or Uri.</summary>
+ public Expression AliasedExpression;
+
+ /// <summary>The namespace being aliased.</summary>
+ public Identifier AliasedNamespace;
+
+ /// <summary>A reference to the type being aliased.</summary>
+ public TypeReference AliasedType;
+
+ /// <summary>The Uri being aliased.</summary>
+ public Identifier AliasedUri;
+
+ /// <summary>
+ /// If an alias definition conflicts with a type definition and this causes an ambiguity, the conflicting type is stored here
+ /// by the code that detects the ambiguity. A later visitor is expected to report an error if this is not null.
+ /// </summary>
+ public TypeNode ConflictingType;
+
+ public bool RestrictToInterfaces;
+ public bool RestrictToClassesAndInterfaces;
+
+ public AliasDefinition()
+ : base(NodeType.AliasDefinition)
+ {
+ }
+ public AliasDefinition(Identifier alias, Expression aliasedExpression)
+ : base(NodeType.AliasDefinition)
+ {
+ this.Alias = alias;
+ this.AliasedExpression = aliasedExpression;
+ }
+ public AliasDefinition(Identifier alias, Expression aliasedExpression, SourceContext sctx)
+ : base(NodeType.AliasDefinition)
+ {
+ this.Alias = alias;
+ this.AliasedExpression = aliasedExpression;
+ this.SourceContext = sctx;
+ }
+ }
+ public class UsedNamespace : Node
+ {
+ public Identifier Namespace;
+ public Identifier URI;
+ public UsedNamespace()
+ : base(NodeType.UsedNamespace)
+ {
+ }
+ public UsedNamespace(Identifier Namespace)
+ : base(NodeType.UsedNamespace)
+ {
+ this.Namespace = Namespace;
+ }
+ public UsedNamespace(Identifier Namespace, SourceContext sctx)
+ : base(NodeType.UsedNamespace)
+ {
+ this.Namespace = Namespace;
+ this.SourceContext = sctx;
+ }
+ }
+#endif
+#if !FxCop
+ public class ExceptionHandler : Node
+ {
+ private NodeType handlerType;
+ private Block tryStartBlock;
+ private Block blockAfterTryEnd;
+ private Block handlerStartBlock;
+ private Block blockAfterHandlerEnd;
+ private Block filterExpression;
+ private TypeNode filterType;
+ public ExceptionHandler()
+ : base(NodeType.ExceptionHandler)
+ {
+ }
+ public NodeType HandlerType
+ {
+ get { return this.handlerType; }
+ set { this.handlerType = value; }
+ }
+ public Block TryStartBlock
+ {
+ get { return this.tryStartBlock; }
+ set { this.tryStartBlock = value; }
+ }
+ public Block BlockAfterTryEnd
+ {
+ get { return this.blockAfterTryEnd; }
+ set { this.blockAfterTryEnd = value; }
+ }
+ public Block HandlerStartBlock
+ {
+ get { return this.handlerStartBlock; }
+ set { this.handlerStartBlock = value; }
+ }
+ public Block BlockAfterHandlerEnd
+ {
+ get { return this.blockAfterHandlerEnd; }
+ set { this.blockAfterHandlerEnd = value; }
+ }
+ public Block FilterExpression
+ {
+ get { return this.filterExpression; }
+ set { this.filterExpression = value; }
+ }
+ public TypeNode FilterType
+ {
+ get { return this.filterType; }
+ set { this.filterType = value; }
+ }
+ }
+#endif
+ public class AttributeNode : Node
+ {
+#if !MinimalReader
+ public bool IsPseudoAttribute;
+#endif
+ public AttributeNode()
+ : base(NodeType.Attribute)
+ {
+ }
+ public AttributeNode(Expression constructor, ExpressionList expressions)
+ : base(NodeType.Attribute)
+ {
+ this.constructor = constructor;
+ this.expressions = expressions;
+ this.target = AttributeTargets.All;
+ }
+#if !MinimalReader
+ public AttributeNode(Expression constructor, ExpressionList expressions, AttributeTargets target)
+ : base(NodeType.Attribute)
+ {
+ this.constructor = constructor;
+ this.expressions = expressions;
+ this.target = target;
+ }
+#endif
+ private Expression constructor;
+ public Expression Constructor
+ {
+ get { return this.constructor; }
+ set { this.constructor = value; }
+ }
+ private ExpressionList expressions;
+ /// <summary>
+ /// Invariant: positional arguments occur first and in order in the expression list. Named arguments
+ /// follow posititional arguments in any order.
+ /// </summary>
+ public ExpressionList Expressions
+ {
+ get { return this.expressions; }
+ set { this.expressions = value; }
+ }
+ private AttributeTargets target;
+ public AttributeTargets Target
+ {
+ get { return this.target; }
+ set { this.target = value; }
+ }
+ private bool allowMultiple;
+ public virtual bool AllowMultiple
+ {
+ get
+ {
+ if (this.usageAttribute == null) this.GetUsageInformation();
+ return this.allowMultiple;
+ }
+ set
+ {
+ this.allowMultiple = value;
+ }
+ }
+ private bool inherited;
+ public virtual bool Inherited
+ {
+ get
+ {
+ if (this.usageAttribute == null) this.GetUsageInformation();
+ return this.inherited;
+ }
+ set
+ {
+ this.inherited = value;
+ }
+ }
+ private AttributeTargets validOn;
+ public virtual AttributeTargets ValidOn
+ {
+ get
+ {
+ if (this.usageAttribute == null) this.GetUsageInformation();
+ return this.validOn;
+ }
+ set
+ {
+ this.validOn = value;
+ }
+ }
+ private TypeNode type;
+ public virtual TypeNode Type
+ {
+ get
+ {
+ if (this.type == null)
+ {
+ MemberBinding mb = this.Constructor as MemberBinding;
+ Member cons = mb == null ? null : mb.BoundMember;
+ this.type = cons == null ? null : cons.DeclaringType;
+ }
+ return this.type;
+ }
+ set
+ {
+ this.type = value;
+ }
+ }
+ private AttributeNode usageAttribute;
+ private void GetUsageInformation()
+ {
+ AttributeNode attr = null;
+ TypeNode attrType = this.Type;
+ while (attrType != null)
+ {
+ attr = attrType.GetAttribute(SystemTypes.AttributeUsageAttribute);
+ if (attr != null) break;
+ attrType = attrType.BaseType;
+ }
+ if (attr == null)
+ {
+ this.usageAttribute = AttributeNode.DoesNotExist;
+ return;
+ }
+ ExpressionList args = attr.Expressions;
+ if (args == null || args.Count < 1) return;
+ Literal lit = args[0] as Literal;
+ if (lit == null || !(lit.Value is int))
+ {
+#if ExtendedRuntime
+ MemberBinding mb = args[0] as MemberBinding;
+ if (mb != null) {
+ Field f = mb.BoundMember as Field;
+ if (f != null && f.IsLiteral) {
+ lit = f.Initializer as Literal;
+ }
+ }
+ if (lit == null || !(lit.Value is int))
+#endif
+ return;
+ }
+ //^ assert lit.Value != null;
+ this.validOn = (AttributeTargets)(int)lit.Value;
+ for (int i = 1, n = args.Count; i < n; i++)
+ {
+ NamedArgument narg = args[i] as NamedArgument;
+ if (narg == null || narg.Name == null) continue;
+ lit = narg.Value as Literal;
+ if (lit == null) continue;
+ if (narg.Name.UniqueIdKey == StandardIds.AllowMultiple.UniqueIdKey)
+ {
+ if (lit.Value == null || !(lit.Value is bool)) continue;
+ this.allowMultiple = (bool)lit.Value;
+ }
+ else if (narg.Name.UniqueIdKey == StandardIds.Inherited.UniqueIdKey)
+ {
+ if (lit.Value == null || !(lit.Value is bool)) continue;
+ this.inherited = (bool)lit.Value;
+ }
+ }
+ }
+ public static readonly AttributeNode DoesNotExist = new AttributeNode();
+#if !NoReflection
+ public virtual System.Attribute GetRuntimeAttribute()
+ {
+ MemberBinding mb = this.Constructor as MemberBinding;
+ if (mb == null) return null;
+ InstanceInitializer constr = mb.BoundMember as InstanceInitializer;
+ if (constr == null) return null;
+ ParameterList parameters = constr.Parameters;
+ int paramCount = parameters == null ? 0 : parameters.Count;
+ object[] argumentValues = new object[paramCount];
+ ExpressionList argumentExpressions = this.Expressions;
+ int exprCount = argumentExpressions == null ? 0 : argumentExpressions.Count;
+ for (int i = 0, j = 0; i < paramCount; i++)
+ {
+ if (j >= exprCount) return null;
+ //^ assert argumentExpressions != null;
+ Expression argExpr = argumentExpressions[j++];
+ Literal lit = argExpr as Literal;
+ if (lit == null) continue;
+ argumentValues[i] = this.GetCoercedLiteralValue(lit.Type, lit.Value);
+ }
+ System.Attribute attr = this.ConstructAttribute(constr, argumentValues);
+ if (attr == null) return null;
+ for (int i = 0; i < exprCount; i++)
+ {
+ //^ assert argumentExpressions != null;
+ NamedArgument namedArg = argumentExpressions[i] as NamedArgument;
+ if (namedArg == null) continue;
+ if (namedArg.Name == null) continue;
+ Literal lit = namedArg.Value as Literal;
+ if (lit == null) continue;
+ object val = this.GetCoercedLiteralValue(lit.Type, lit.Value);
+ if (namedArg.IsCustomAttributeProperty)
+ {
+ TypeNode t = constr.DeclaringType;
+ while (t != null)
+ {
+ Property prop = t.GetProperty(namedArg.Name);
+ if (prop != null)
+ {
+ this.SetAttributeProperty(prop, attr, val);
+ t = null;
+ }
+ else
+ t = t.BaseType;
+ }
+ }
+ else
+ {
+ TypeNode t = constr.DeclaringType;
+ while (t != null)
+ {
+ Field f = constr.DeclaringType.GetField(namedArg.Name);
+ if (f != null)
+ {
+ System.Reflection.FieldInfo fieldInfo = f.GetFieldInfo();
+ if (fieldInfo != null) fieldInfo.SetValue(attr, val);
+ t = null;
+ }
+ else
+ t = t.BaseType;
+ }
+ }
+ }
+ return attr;
+ }
+ /// <summary>
+ /// Gets the value of the literal coercing literals of TypeNode, EnumNode, TypeNode[], and EnumNode[] as needed.
+ /// </summary>
+ /// <param name="type">A TypeNode representing the type of the literal</param>
+ /// <param name="value">The value of the literal</param>
+ /// <returns>An object that has been coerced to the appropiate runtime type</returns>
+ protected object GetCoercedLiteralValue(TypeNode type, object value)
+ {
+ if (type == null || value == null) return null;
+ switch (type.typeCode)
+ {
+ case ElementType.Class:
+ return ((TypeNode)value).GetRuntimeType();
+ case ElementType.ValueType:
+ return System.Enum.ToObject(type.GetRuntimeType(), value);
+ case ElementType.SzArray:
+ return this.GetCoercedArrayLiteral((ArrayType)type, (Array)value);
+ default:
+ Literal lit = value as Literal;
+ if (lit != null && type == CoreSystemTypes.Object && lit.Type is EnumNode)
+ return this.GetCoercedLiteralValue(lit.Type, lit.Value);
+ break;
+ }
+ return value;
+ }
+ /// <summary>
+ /// Gets the array literal in arrayValue coercing TypeNode[] and EnumNode[] as needed.
+ /// </summary>
+ /// <param name="arrayType">A TypeNode representing the array type</param>
+ /// <param name="arrayValue">The value of the array literal to coerce</param>
+ /// <returns>An Array object that has been coerced to the appropriate runtime type</returns>
+ protected Array GetCoercedArrayLiteral(ArrayType arrayType, Array arrayValue)
+ {
+ if (arrayType == null) return null;
+ if (arrayValue == null) return null;
+ // Multi-dimensional arrays are not legal in attribute instances according section 17.1.3 of the C# 1.0 spec
+ if (arrayValue.Rank != 1) return null;
+ TypeNode elemType = arrayType.ElementType;
+ if (elemType.typeCode != ElementType.ValueType && elemType.typeCode != ElementType.Class)
+ return arrayValue;
+ int arraySize = arrayValue.GetLength(0);
+ Type et = elemType.GetRuntimeType();
+ if (et == null) return null;
+ Array val = Array.CreateInstance(et, arraySize);
+ for (int i = 0; i < arraySize; i++)
+ val.SetValue(this.GetCoercedLiteralValue(elemType, arrayValue.GetValue(i)), i);
+ return val;
+ }
+ private void SetAttributeProperty(Property/*!*/ prop, System.Attribute attr, object val)
+ {
+ //This could execute partially trusted code, so set up a very restrictive execution environment
+ //TODO: skip this if the attribute is from a trusted assembly
+ System.Reflection.PropertyInfo propInfo = prop.GetPropertyInfo();
+ if (propInfo == null) return;
+ //Because we invoke the setter through reflection, a stack walk is performed. The following two commented-out statements
+ //would cause the stack walk to fail.
+ //For now, we will run the setter in full trust until we work around this.
+ //For VS2005 and later, we will construct a DynamicMethod, wrap it in a delegate, and invoke that.
+
+ //System.Security.PermissionSet perm = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None);
+ //perm.PermitOnly();
+ try
+ {
+ propInfo.SetValue(attr, val, null);
+ }
+ catch { }
+ }
+ private System.Attribute ConstructAttribute(InstanceInitializer/*!*/ constr, object[] argumentValues)
+ {
+ //This could execute partially trusted code, so set up a very restrictive execution environment
+ //TODO: skip this if the attribute is from a trusted assembly
+ System.Reflection.ConstructorInfo consInfo = constr.GetConstructorInfo();
+ if (consInfo == null) return null;
+ //Because we invoke the constructor through reflection, a stack walk is performed. The following two commented-out statements
+ //would cause the stack walk to fail.
+ //For VS2003 and earlier, we will run the constructor in full trust.
+ //For VS2005 and later, we will construct a DynamicMethod, wrap it in a delegate, and invoke that.
+
+ //System.Security.PermissionSet perm = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None);
+ //perm.PermitOnly();
+ try
+ {
+ return consInfo.Invoke(argumentValues) as System.Attribute;
+ }
+ catch { }
+ return null;
+ }
+#endif
+ public Expression GetPositionalArgument(int position)
+ {
+ if (this.Expressions == null || this.Expressions.Count <= position) return null;
+ Expression e = this.Expressions[position];
+ NamedArgument na = e as NamedArgument;
+ if (na != null) return null;
+ return e;
+ }
+ public Expression GetNamedArgument(Identifier name)
+ {
+ if (name == null || this.Expressions == null) return null;
+ foreach (Expression e in this.Expressions)
+ {
+ NamedArgument na = e as NamedArgument;
+ if (na == null) continue;
+ if (na.Name == null) continue;
+ if (na.Name.UniqueIdKey == name.UniqueIdKey) return na.Value;
+ }
+ return null;
+ }
+ }
+ public class SecurityAttribute : Node
+ {
+ public SecurityAttribute()
+ : base(NodeType.SecurityAttribute)
+ {
+ }
+ private System.Security.Permissions.SecurityAction action;
+ public System.Security.Permissions.SecurityAction Action
+ {
+ get { return this.action; }
+ set { this.action = value; }
+ }
+ private AttributeList permissionAttributes;
+ public AttributeList PermissionAttributes
+ {
+ get { return this.permissionAttributes; }
+ set { this.permissionAttributes = value; }
+ }
+ protected string serializedPermissions;
+ public string SerializedPermissions
+ {
+ get
+ {
+#if !NoReflection || FxCop
+ if (this.serializedPermissions == null && this.PermissionAttributes != null)
+ {
+ lock (this)
+ {
+ if (this.serializedPermissions != null) return this.serializedPermissions;
+ System.Security.PermissionSet permissions = this.Permissions;
+ if (permissions == null) return null;
+ System.Security.SecurityElement xml = permissions.ToXml();
+ if (xml == null) return null;
+ this.serializedPermissions = xml.ToString();
+ //TODO: if the target platform is different from the host platform, replace references to host platform
+ //assemblies with references to target platform assemblies
+ }
+ }
+#endif
+ return this.serializedPermissions;
+ }
+ set
+ {
+ this.serializedPermissions = value;
+ }
+ }
+#if !NoReflection || FxCop
+ protected System.Security.PermissionSet permissions;
+ public System.Security.PermissionSet Permissions
+ {
+ get
+ {
+ if (this.permissions == null)
+ {
+ lock (this)
+ {
+ if (this.permissions != null) return this.permissions;
+ System.Security.PermissionSet permissions = null;
+#if !FxCop
+ if (this.PermissionAttributes != null)
+ {
+ permissions = this.InstantiatePermissionAttributes();
+ }
+ else if (this.serializedPermissions != null)
+ {
+ permissions = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None);
+ permissions.FromXml(this.GetSecurityElement());
+ }
+#elif !TestBuild
+ permissions = PermissionsHelper.GetPermissions(this);
+#endif
+ this.permissions = permissions;
+ }
+ }
+ return this.permissions;
+ }
+ set
+ {
+ this.permissions = value;
+ }
+ }
+#endif
+#if !NoReflection
+ protected System.Security.SecurityElement GetSecurityElement()
+ {
+#if WHIDBEY
+ return System.Security.SecurityElement.FromString(this.serializedPermissions);
+#else
+ System.Reflection.Assembly mscorlib = CoreSystemTypes.SystemAssembly.GetRuntimeAssembly();
+ if (mscorlib == null) { Debug.Fail(""); return null; }
+ Type parserType = mscorlib.GetType("System.Security.Util.Parser", true, false);
+ if (parserType == null) { Debug.Fail(""); return null; }
+ System.Reflection.MethodInfo getTopElement = parserType.GetMethod("GetTopElement", BindingFlags.NonPublic|BindingFlags.Instance, null, new Type[]{}, null);
+ if (getTopElement == null) { Debug.Fail(""); return null; }
+ object parser = Activator.CreateInstance(parserType, BindingFlags.Instance|BindingFlags.NonPublic, null, new Object[]{this.serializedPermissions}, null);
+ return (System.Security.SecurityElement)getTopElement.Invoke(parser, null);
+#endif
+ }
+ protected System.Security.PermissionSet InstantiatePermissionAttributes()
+ {
+ System.Security.PermissionSet permissions = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None);
+ AttributeList permissionAttributes = this.PermissionAttributes;
+ for (int i = 0, n = permissionAttributes == null ? 0 : permissionAttributes.Count; i < n; i++)
+ {
+ //^ assert permissionAttributes != null;
+ object result = this.GetPermissionOrSetOfPermissionsFromAttribute(permissionAttributes[i]);
+ if (result == null) continue;
+ if (result is System.Security.PermissionSet)
+ permissions = permissions.Union((System.Security.PermissionSet)result);
+ else
+ {
+ System.Security.IPermission permission = result as System.Security.IPermission;
+ if (permission == null) continue;
+ permissions.AddPermission(permission);
+ }
+ }
+ return permissions;
+ }
+ protected object GetPermissionOrSetOfPermissionsFromAttribute(AttributeNode attr)
+ {
+ if (attr == null) return null;
+ System.Security.Permissions.SecurityAttribute secAttr = attr.GetRuntimeAttribute() as System.Security.Permissions.SecurityAttribute;
+ if (secAttr == null) return null;
+ System.Security.Permissions.PermissionSetAttribute pSetAttr = secAttr as System.Security.Permissions.PermissionSetAttribute;
+ if (pSetAttr != null)
+ return pSetAttr.CreatePermissionSet();
+ else
+ return this.CreatePermission(secAttr);
+ }
+ private System.Security.IPermission CreatePermission(System.Security.Permissions.SecurityAttribute/*!*/ secAttr)
+ {
+ //This could execute partially trusted code, so set up a very restrictive execution environment
+ System.Security.PermissionSet perm = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None);
+ //TODO: add permissions if the attribute is from a trusted assembly
+ perm.PermitOnly();
+ try
+ {
+ return secAttr.CreatePermission();
+ }
+ catch { }
+ return null;
+ }
+#endif
+ }
+ public struct Resource
+ {
+ private bool isPublic;
+ private string name;
+ private Module definingModule;
+ private byte[] data;
+ public bool IsPublic
+ {
+ get { return this.isPublic; }
+ set { this.isPublic = value; }
+ }
+ public string Name
+ {
+ get { return this.name; }
+ set { this.name = value; }
+ }
+ public Module DefiningModule
+ {
+ get { return this.definingModule; }
+ set { this.definingModule = value; }
+ }
+ public byte[] Data
+ {
+ get { return this.data; }
+ set { this.data = value; }
+ }
+ }
+ public struct Win32Resource
+ {
+ private string typeName;
+ private int typeId;
+ private string name;
+ private int id;
+ private int languageId;
+ private int codePage;
+ private byte[] data;
+ public string TypeName
+ {
+ get { return this.typeName; }
+ set { this.typeName = value; }
+ }
+ public int TypeId
+ {
+ get { return this.typeId; }
+ set { this.typeId = value; }
+ }
+ public string Name
+ {
+ get { return this.name; }
+ set { this.name = value; }
+ }
+ public int Id
+ {
+ get { return this.id; }
+ set { this.id = value; }
+ }
+ public int LanguageId
+ {
+ get { return this.languageId; }
+ set { this.languageId = value; }
+ }
+ public int CodePage
+ {
+ get { return this.codePage; }
+ set { this.codePage = value; }
+ }
+ public byte[] Data
+ {
+ get { return this.data; }
+ set { this.data = value; }
+ }
+ }
+#if FxCop
+ public class ModuleNode : Node, IDisposable{
+#else
+ public class Module : Node, IDisposable
+ {
+#endif
+ internal Reader reader;
+ public delegate void TypeNodeListProvider(Module/*!*/ module);
+ protected TypeNodeListProvider provideTypeNodeList;
+ public delegate TypeNode TypeNodeProvider(Identifier/*!*/ @namespace, Identifier/*!*/ name);
+ protected TypeNodeProvider provideTypeNode;
+ protected TrivialHashtable namespaceTable = new TrivialHashtable();
+ protected NamespaceList namespaceList;
+ protected int savedTypesLength;
+ public delegate void CustomAttributeProvider(Module/*!*/ module);
+ protected CustomAttributeProvider provideCustomAttributes;
+ public delegate void ResourceProvider(Module/*!*/ module);
+ protected ResourceProvider provideResources;
+ public delegate AssemblyNode AssemblyReferenceResolver(AssemblyReference/*!*/ assemblyReference, Module/*!*/ referencingModule);
+ public event AssemblyReferenceResolver AssemblyReferenceResolution;
+ public event AssemblyReferenceResolver AssemblyReferenceResolutionAfterProbingFailed;
+#if !MinimalReader
+ public delegate void PostAssemblyLoadProcessor(AssemblyNode loadedAssembly);
+ public event PostAssemblyLoadProcessor AfterAssemblyLoad;
+#endif
+#if !NoXml
+ public delegate XmlDocument DocumentationResolver(Module referencingModule);
+ public event DocumentationResolver DocumentationResolution = null;
+#endif
+#if !MinimalReader
+ public bool IsNormalized;
+#endif
+#if !NoWriter
+ public bool UsePublicKeyTokensForAssemblyReferences = true;
+#endif
+ internal int FileAlignment = 512;
+ internal readonly static object GlobalLock = new object();
+#if !NoWriter
+ public bool StripOptionalModifiersFromLocals = true;
+#endif
+#if FxCop
+ public ModuleNode()
+#else
+ public Module()
+#endif
+ : base(NodeType.Module)
+ {
+#if !MinimalReader
+ this.IsNormalized = false;
+#endif
+ }
+#if FxCop
+ public ModuleNode(TypeNodeProvider provider, TypeNodeListProvider listProvider, CustomAttributeProvider provideCustomAttributes, ResourceProvider provideResources)
+#else
+ public Module(TypeNodeProvider provider, TypeNodeListProvider listProvider, CustomAttributeProvider provideCustomAttributes, ResourceProvider provideResources)
+#endif
+ : base(NodeType.Module)
+ {
+ this.provideCustomAttributes = provideCustomAttributes;
+ this.provideResources = provideResources;
+ this.provideTypeNode = provider;
+ this.provideTypeNodeList = listProvider;
+#if !MinimalReader
+ this.IsNormalized = true;
+#endif
+ }
+ public virtual void Dispose()
+ {
+ if (this.reader != null) this.reader.Dispose();
+ this.reader = null;
+ ModuleReferenceList mrefs = this.moduleReferences;
+ for (int i = 0, n = mrefs == null ? 0 : mrefs.Count; i < n; i++)
+ {
+ //^ assert mrefs != null;
+ ModuleReference mr = mrefs[i];
+ if (mr != null && mr.Module == null) continue;
+ mr.Module.Dispose();
+ }
+ this.moduleReferences = null;
+ }
+ private AssemblyReferenceList assemblyReferences;
+ public AssemblyReferenceList AssemblyReferences
+ {
+ get { return this.assemblyReferences; }
+ set { this.assemblyReferences = value; }
+ }
+ private AssemblyNode containingAssembly;
+ /// <summary>The assembly, if any, that includes this module in its ModuleReferences.</summary>
+ public AssemblyNode ContainingAssembly
+ {
+ get { return this.containingAssembly; }
+ set { this.containingAssembly = value; }
+ }
+ private string directory;
+ public string Directory
+ {
+ get { return this.directory; }
+ set { this.directory = value; }
+ }
+ private AssemblyHashAlgorithm hashAlgorithm = AssemblyHashAlgorithm.SHA1;
+ public AssemblyHashAlgorithm HashAlgorithm
+ {
+ get { return this.hashAlgorithm; }
+ set { this.hashAlgorithm = value; }
+ }
+ private byte[] hashValue;
+ public byte[] HashValue
+ {
+ get { return this.hashValue; }
+ set { this.hashValue = value; }
+ }
+ private ModuleKindFlags kind;
+ /// <summary>An enumeration that indicates if the module is an executable, library or resource, and so on.</summary>
+ public ModuleKindFlags Kind
+ {
+ get { return this.kind; }
+ set { this.kind = value; }
+ }
+ private string location;
+ /// <summary>The path of the file from which this module or assembly was loaded or will be stored in.</summary>
+ public string Location
+ {
+ get { return this.location; }
+ set { this.location = value; }
+ }
+ private System.Guid mvid;
+ public System.Guid Mvid
+ {
+ get { return this.mvid; }
+ set { this.mvid = value; }
+ }
+ private string targetRuntimeVersion;
+ /// <summary>Identifies the version of the CLR that is required to load this module or assembly.</summary>
+ public string TargetRuntimeVersion
+ {
+ get { return this.targetRuntimeVersion; }
+ set { this.targetRuntimeVersion = value; }
+ }
+ private int linkerMajorVersion = 6;
+ public int LinkerMajorVersion
+ {
+ get { return this.linkerMajorVersion; }
+ set { this.linkerMajorVersion = value; }
+ }
+ private int linkerMinorVersion;
+ public int LinkerMinorVersion
+ {
+ get { return this.linkerMinorVersion; }
+ set { this.linkerMinorVersion = value; }
+ }
+ private int metadataFormatMajorVersion;
+ public int MetadataFormatMajorVersion
+ {
+ get { return this.metadataFormatMajorVersion; }
+ set { this.metadataFormatMajorVersion = value; }
+ }
+ private int metadataFormatMinorVersion;
+ public int MetadataFormatMinorVersion
+ {
+ get { return this.metadataFormatMinorVersion; }
+ set { this.metadataFormatMinorVersion = value; }
+ }
+ private string name;
+ /// <summary>The name of the module or assembly. Includes the file extension if the module is not an assembly.</summary>
+ public string Name
+ {
+ get { return this.name; }
+ set { this.name = value; }
+ }
+ private PEKindFlags peKind = PEKindFlags.ILonly;
+ public PEKindFlags PEKind
+ {
+ get { return this.peKind; }
+ set { this.peKind = value; }
+ }
+ private bool trackDebugData;
+ public bool TrackDebugData
+ {
+ get { return this.trackDebugData; }
+ set { this.trackDebugData = value; }
+ }
+#if !FxCop
+ private ArrayList metadataImportErrors;
+ /// <summary>
+ /// If any exceptions were encountered while reading in this module, they are recorded here. Since reading is lazy,
+ /// this list can grow dynamically during the use of a module.
+ /// </summary>
+ public ArrayList MetadataImportErrors
+ {
+ get { return this.metadataImportErrors; }
+ set { this.metadataImportErrors = value; }
+ }
+#endif
+ protected AttributeList attributes;
+ /// <summary>
+ /// The attributes associated with this module or assembly. This corresponds to C# custom attributes with the assembly or module target specifier.
+ /// </summary>
+ public virtual AttributeList Attributes
+ {
+ get
+ {
+ if (this.attributes != null) return this.attributes;
+ if (this.provideCustomAttributes != null)
+ {
+ lock (Module.GlobalLock)
+ {
+ if (this.attributes == null)
+ this.provideCustomAttributes(this);
+ }
+ }
+ else
+ this.attributes = new AttributeList();
+ return this.attributes;
+ }
+ set
+ {
+ this.attributes = value;
+ }
+ }
+
+ protected SecurityAttributeList securityAttributes;
+ /// <summary>
+ /// Declarative security for the module or assembly.
+ /// </summary>
+ public virtual SecurityAttributeList SecurityAttributes
+ {
+ get
+ {
+ if (this.securityAttributes != null) return this.securityAttributes;
+ if (this.provideCustomAttributes != null)
+ {
+ AttributeList dummy = this.Attributes; //As a side effect, this.securityAttributes gets populated
+ if (dummy != null) dummy = null;
+ }
+ else
+ this.securityAttributes = new SecurityAttributeList();
+ return this.securityAttributes;
+ }
+ set
+ {
+ this.securityAttributes = value;
+ }
+ }
+#if !MinimalReader
+ /// <summary>The source code, if any, corresponding to the value in Documentation.</summary>
+ public Node DocumentationNode;
+#endif
+#if !NoXml
+ protected XmlDocument documentation;
+ /// <summary>An XML Document Object Model for a document containing all of the documentation comments applicable to members
+ /// defined in this module.</summary>
+ public virtual XmlDocument Documentation
+ {
+ get
+ {
+ XmlDocument documentation = this.documentation;
+ if (documentation != null) return documentation;
+ if (this.DocumentationResolution != null)
+ documentation = this.documentation = this.DocumentationResolution(this);
+ if (documentation != null) return documentation;
+ XmlDocument doc = null;
+ if (this.Directory != null && this.Name != null)
+ {
+ string fileName = this.Name + ".xml";
+ System.Globalization.CultureInfo cc = System.Globalization.CultureInfo.CurrentUICulture;
+ while (cc != null && cc != System.Globalization.CultureInfo.InvariantCulture)
+ {
+ doc = this.ProbeForXmlDocumentation(this.Directory, cc.Name, fileName);
+ if (doc != null) break;
+ cc = cc.Parent;
+ }
+ if (doc == null)
+ doc = this.ProbeForXmlDocumentation(this.Directory, null, fileName);
+ }
+ if (doc == null) doc = new XmlDocument();
+ return this.documentation = doc;
+ }
+ set
+ {
+ this.documentation = value;
+ }
+ }
+ public virtual XmlDocument ProbeForXmlDocumentation(string dir, string subDir, string fileName)
+ {
+ try
+ {
+ if (dir == null || fileName == null) return null;
+ if (subDir != null) dir = Path.Combine(dir, subDir);
+ string docFileName = Path.Combine(dir, fileName);
+ if (File.Exists(docFileName))
+ {
+ XmlDocument doc = new XmlDocument();
+ using (TextReader reader = File.OpenText(docFileName))
+ {
+ doc.Load(reader);
+ return doc;
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ if (this.MetadataImportErrors == null) this.MetadataImportErrors = new ArrayList();
+ this.MetadataImportErrors.Add(e);
+ }
+ return null;
+ }
+#endif
+ protected internal static readonly Method NoSuchMethod = new Method();
+ protected Method entryPoint;
+ /// <summary>If this module is an executable, this method is the one that gets called to start the execution of managed code.</summary>
+ public virtual Method EntryPoint
+ {
+ get
+ {
+ if (this.entryPoint == null)
+ {
+ if (this.provideCustomAttributes != null)
+ {
+ AttributeList dummy = this.Attributes; //Gets the entry point as a side effect
+ if (dummy != null) dummy = null;
+ }
+ else
+ this.entryPoint = Module.NoSuchMethod;
+ }
+ if (this.entryPoint == Module.NoSuchMethod) return null;
+ return this.entryPoint;
+ }
+ set
+ {
+ this.entryPoint = value;
+ }
+ }
+ protected ModuleReferenceList moduleReferences;
+ /// <summary>The list of modules (excluding assemblies) defining members that are referred to in this module or assembly.</summary>
+ public ModuleReferenceList ModuleReferences
+ {
+ get
+ {
+ //Populating the type list may cause module references to be added
+ if (this.Types == null) return this.moduleReferences;
+ return this.moduleReferences;
+ }
+ set
+ {
+ this.moduleReferences = value;
+ }
+ }
+#if !MinimalReader
+ public virtual bool ContainsModule(Module module)
+ {
+ if (module == null || this.ModuleReferences == null || this.ModuleReferences.Count == 0) return false;
+ int n = this.ModuleReferences.Count;
+ for (int i = 0; i < n; ++i)
+ {
+ ModuleReference mr = this.ModuleReferences[i];
+ if (mr == null) continue;
+ if (mr.Module == module)
+ return true;
+ }
+ return false;
+ }
+#endif
+ protected ResourceList resources;
+ /// <summary>
+ /// A list of managed resources linked or embedded into this module or assembly.
+ /// </summary>
+ public virtual ResourceList Resources
+ {
+ get
+ {
+ if (this.resources != null) return this.resources;
+ if (this.provideResources != null)
+ {
+ lock (Module.GlobalLock)
+ {
+ if (this.resources == null)
+ this.provideResources(this);
+ }
+ }
+ else
+ this.resources = new ResourceList();
+ return this.resources;
+ }
+ set
+ {
+ this.resources = value;
+ }
+ }
+ protected Win32ResourceList win32Resources;
+ /// <summary>
+ /// A list of Win32 resources embedded in this module or assembly.
+ /// </summary>
+ public virtual Win32ResourceList Win32Resources
+ {
+ get
+ {
+ if (this.win32Resources != null) return this.win32Resources;
+ if (this.provideResources != null)
+ {
+ ResourceList dummy = this.Resources; //gets the win32 resources as as side effect
+ if (dummy != null) dummy = null;
+ }
+ else
+ this.win32Resources = new Win32ResourceList();
+ return this.win32Resources;
+ }
+ set
+ {
+ this.win32Resources = value;
+ }
+ }
+#if !NoWriter
+ public virtual void AddWin32ResourceFile(string win32ResourceFilePath)
+ {
+ if (win32ResourceFilePath == null) return;
+ Writer.AddWin32ResourceFileToModule(this, win32ResourceFilePath);
+ }
+ public virtual void AddWin32ResourceFile(Stream win32ResourceStream)
+ {
+ if (win32ResourceStream == null) return;
+ Writer.AddWin32ResourceFileToModule(this, win32ResourceStream);
+ }
+ public virtual void AddWin32Icon(string win32IconFilePath)
+ {
+ if (win32IconFilePath == null) return;
+ Writer.AddWin32Icon(this, win32IconFilePath);
+ }
+ public virtual void AddWin32Icon(Stream win32IconStream)
+ {
+ Writer.AddWin32Icon(this, win32IconStream);
+ }
+ public void AddWin32VersionInfo(CompilerOptions options)
+ {
+ if (options == null) return;
+ Writer.AddWin32VersionInfo(this, options);
+ }
+#endif
+ /// <summary>
+ /// Gets the first attribute of the given type in the custom attribute list of this module. Returns null if none found.
+ /// This should not be called until the module has been processed to replace symbolic references
+ /// to members with references to the actual members.
+ /// </summary>
+ public virtual AttributeNode GetAttribute(TypeNode attributeType)
+ {
+ AttributeList attributes = this.GetAttributes(attributeType, 1);
+ if (attributes != null && attributes.Count > 0)
+ return attributes[0];
+ return null;
+ }
+
+ public virtual AttributeList GetAttributes(TypeNode attributeType)
+ {
+ return GetAttributes(attributeType, Int32.MaxValue);
+ }
+
+ public virtual AttributeList GetAttributes(TypeNode attributeType, int maxCount)
+ {
+ AttributeList foundAttributes = new AttributeList();
+ if (attributeType == null) return foundAttributes;
+ AttributeList attributes = this.Attributes;
+ for (int i = 0, count = 0, n = attributes == null ? 0 : attributes.Count; i < n && count < maxCount; i++)
+ {
+ AttributeNode attr = attributes[i];
+ if (attr == null) continue;
+ MemberBinding mb = attr.Constructor as MemberBinding;
+ if (mb != null)
+ {
+ if (mb.BoundMember == null) continue;
+ if (mb.BoundMember.DeclaringType != attributeType) continue;
+ foundAttributes.Add(attr);
+ count++;
+ continue;
+ }
+ Literal lit = attr.Constructor as Literal;
+ if (lit == null) continue;
+ if ((lit.Value as TypeNode) != attributeType) continue;
+ foundAttributes.Add(attr);
+ count++;
+ }
+ return foundAttributes;
+ }
+#if !NoXml
+ protected TrivialHashtable memberDocumentationCache;
+ public TrivialHashtable GetMemberDocumentationCache()
+ {
+ TrivialHashtable cache = this.memberDocumentationCache;
+ if (cache != null) return cache;
+ lock (this)
+ {
+ if (this.memberDocumentationCache != null) return this.memberDocumentationCache;
+ XmlDocument doc = this.Documentation;
+ if (doc == null && this.ContainingAssembly != null && this.ContainingAssembly != this)
+ return this.memberDocumentationCache = this.ContainingAssembly.memberDocumentationCache;
+ cache = this.memberDocumentationCache = new TrivialHashtable();
+ if (doc == null) return cache;
+ XmlNode docElem = doc.DocumentElement;
+ if (docElem == null) return cache;
+ XmlNode membersNode = null;
+ if (docElem.HasChildNodes)
+ {
+ foreach (XmlNode dec in docElem.ChildNodes)
+ if (dec.Name == "members") { membersNode = dec; break; }
+ }
+ if (membersNode == null) return cache;
+ if (membersNode.HasChildNodes)
+ {
+ foreach (XmlNode member in membersNode.ChildNodes)
+ {
+ if (member.Name != "member") continue;
+ XmlNode nameAttr = member.Attributes.GetNamedItem("name");
+ if (nameAttr == null) continue;
+ cache[Identifier.For(nameAttr.Value).UniqueIdKey] = member;
+ }
+ }
+ return cache;
+ }
+ }
+#endif
+ protected TrivialHashtable validNamespaces;
+ public NamespaceList GetNamespaceList()
+ {
+ if (this.reader != null) return this.GetNamespaceListFromReader();
+#if !MinimalReader
+ TypeNodeList types = this.Types;
+ int n = types == null ? 0 : types.Count;
+ if (this.namespaceList == null || n > this.savedTypesLength)
+ {
+ lock (this)
+ {
+ if (this.namespaceList != null && this.types != null && this.types.Count == this.savedTypesLength)
+ return this.namespaceList;
+ NamespaceList nsList = this.namespaceList = new NamespaceList();
+ TrivialHashtable nsTable = this.validNamespaces = new TrivialHashtable();
+ for (int i = 0; i < n; i++)
+ {
+ //^ assert this.types != null;
+ TypeNode t = this.types[i];
+ if (t == null) continue;
+ if (t.Namespace == null) t.Namespace = Identifier.Empty;
+ Namespace ns = nsTable[t.Namespace.UniqueIdKey] as Namespace;
+ if (ns != null)
+ {
+ if (t.IsPublic) ns.isPublic = true;
+ ns.Types.Add(t); continue;
+ }
+ ns = new Namespace(t.Namespace);
+ ns.isPublic = t.IsPublic;
+ ns.Types = new TypeNodeList();
+ ns.Types.Add(t);
+ nsTable[t.Namespace.UniqueIdKey] = ns;
+ nsList.Add(ns);
+ }
+ }
+ }
+#endif
+ return this.namespaceList;
+ }
+ private NamespaceList GetNamespaceListFromReader()
+ //^ requires this.reader != null;
+ {
+ if (this.namespaceList == null)
+ {
+ lock (Module.GlobalLock)
+ {
+ this.reader.GetNamespaces();
+ NamespaceList nsList = this.namespaceList = this.reader.namespaceList;
+ TrivialHashtable nsTable = this.validNamespaces = new TrivialHashtable();
+ for (int i = 0, n = nsList == null ? 0 : nsList.Count; i < n; i++)
+ {
+ //^ assert nsList != null;
+ Namespace ns = nsList[i];
+ if (ns == null || ns.Name == null) continue;
+ ns.ProvideTypes = new Namespace.TypeProvider(this.GetTypesForNamespace);
+ nsTable[ns.Name.UniqueIdKey] = ns;
+ }
+ }
+ }
+ return this.namespaceList;
+ }
+ private void GetTypesForNamespace(Namespace nspace, object handle)
+ {
+ if (nspace == null || nspace.Name == null) return;
+ lock (Module.GlobalLock)
+ {
+ int key = nspace.Name.UniqueIdKey;
+ TypeNodeList types = this.Types;
+ TypeNodeList nsTypes = nspace.Types = new TypeNodeList();
+ for (int i = 0, n = types == null ? 0 : types.Count; i < n; i++)
+ {
+ TypeNode t = types[i];
+ if (t == null || t.Namespace == null) continue;
+ if (t.Namespace.UniqueIdKey == key) nsTypes.Add(t);
+ }
+ }
+ }
+ public bool IsValidNamespace(Identifier nsName)
+ {
+ if (nsName == null) return false;
+ this.GetNamespaceList();
+ //^ assert this.validNamespaces != null;
+ return this.validNamespaces[nsName.UniqueIdKey] != null;
+ }
+ public bool IsValidTypeName(Identifier nsName, Identifier typeName)
+ {
+ if (nsName == null || typeName == null) return false;
+ if (!this.IsValidNamespace(nsName)) return false;
+ if (this.reader != null) return this.reader.IsValidTypeName(nsName, typeName);
+ return this.GetType(nsName, typeName) != null;
+ }
+ public Module GetNestedModule(string moduleName)
+ {
+ if (this.Types == null) { Debug.Assert(false); } //Just get the types to pull in any exported types
+ ModuleReferenceList moduleReferences = this.ModuleReferences; //This should now contain all interesting referenced modules
+ for (int i = 0, n = moduleReferences == null ? 0 : moduleReferences.Count; i < n; i++)
+ {
+ ModuleReference mref = moduleReferences[i];
+ if (mref == null) continue;
+ if (mref.Name == moduleName) return mref.Module;
+ }
+ return null;
+ }
+ internal TrivialHashtableUsingWeakReferences/*!*/ StructurallyEquivalentType
+ {
+ get
+ {
+ if (this.structurallyEquivalentType == null)
+ this.structurallyEquivalentType = new TrivialHashtableUsingWeakReferences();
+ return this.structurallyEquivalentType;
+ }
+ }
+ private TrivialHashtableUsingWeakReferences structurallyEquivalentType;
+ /// <summary>
+ /// The identifier represents the structure via some mangling scheme. The result can be either from this module,
+ /// or any module this module has a reference to.
+ /// </summary>
+ public virtual TypeNode GetStructurallyEquivalentType(Identifier ns, Identifier/*!*/ id)
+ {
+ return this.GetStructurallyEquivalentType(ns, id, id, true);
+ }
+ public virtual TypeNode GetStructurallyEquivalentType(Identifier ns, Identifier/*!*/ id, Identifier uniqueMangledName, bool lookInReferencedAssemblies)
+ {
+ if (uniqueMangledName == null) uniqueMangledName = id;
+ TypeNode result = (TypeNode)this.StructurallyEquivalentType[uniqueMangledName.UniqueIdKey];
+ if (result == Class.DoesNotExist) return null;
+ if (result != null) return result;
+ lock (Module.GlobalLock)
+ {
+ result = this.GetType(ns, id);
+ if (result != null)
+ {
+ this.StructurallyEquivalentType[uniqueMangledName.UniqueIdKey] = result;
+ return result;
+ }
+ if (!lookInReferencedAssemblies)
+ goto notfound;
+ AssemblyReferenceList refs = this.AssemblyReferences;
+ for (int i = 0, n = refs == null ? 0 : refs.Count; i < n; i++)
+ {
+ AssemblyReference ar = refs[i];
+ if (ar == null) continue;
+ AssemblyNode a = ar.Assembly;
+ if (a == null) continue;
+ result = a.GetType(ns, id);
+ if (result != null)
+ {
+ this.StructurallyEquivalentType[uniqueMangledName.UniqueIdKey] = result;
+ return result;
+ }
+ }
+ notfound:
+ this.StructurallyEquivalentType[uniqueMangledName.UniqueIdKey] = Class.DoesNotExist;
+ return null;
+ }
+ }
+ public virtual TypeNode GetType(Identifier @namespace, Identifier name, bool lookInReferencedAssemblies)
+ {
+ return this.GetType(@namespace, name, lookInReferencedAssemblies, lookInReferencedAssemblies ? new TrivialHashtable() : null);
+ }
+ protected virtual TypeNode GetType(Identifier @namespace, Identifier name, bool lookInReferencedAssemblies, TrivialHashtable assembliesAlreadyVisited)
+ {
+ if (assembliesAlreadyVisited != null)
+ {
+ if (assembliesAlreadyVisited[this.UniqueKey] != null) return null;
+ assembliesAlreadyVisited[this.UniqueKey] = this;
+ }
+ TypeNode result = this.GetType(@namespace, name);
+ if (result != null || !lookInReferencedAssemblies) return result;
+ AssemblyReferenceList refs = this.AssemblyReferences;
+ for (int i = 0, n = refs == null ? 0 : refs.Count; i < n; i++)
+ {
+ AssemblyReference ar = refs[i];
+ if (ar == null) continue;
+ AssemblyNode a = ar.Assembly;
+ if (a == null) continue;
+ result = a.GetType(@namespace, name, true, assembliesAlreadyVisited);
+ if (result != null) return result;
+ }
+ return null;
+ }
+ public virtual TypeNode GetType(Identifier @namespace, Identifier name)
+ {
+ if (@namespace == null || name == null) return null;
+ TypeNode result = null;
+ if (this.namespaceTable == null) this.namespaceTable = new TrivialHashtable();
+ TrivialHashtable nsTable = (TrivialHashtable)this.namespaceTable[@namespace.UniqueIdKey];
+ if (nsTable != null)
+ {
+ result = (TypeNode)nsTable[name.UniqueIdKey];
+ if (result == Class.DoesNotExist) return null;
+ if (result != null) return result;
+ }
+ else
+ {
+ lock (Module.GlobalLock)
+ {
+ nsTable = (TrivialHashtable)this.namespaceTable[@namespace.UniqueIdKey];
+ if (nsTable == null)
+ this.namespaceTable[@namespace.UniqueIdKey] = nsTable = new TrivialHashtable(32);
+ }
+ }
+ if (this.provideTypeNode != null)
+ {
+ lock (Module.GlobalLock)
+ {
+ result = (TypeNode)nsTable[name.UniqueIdKey];
+ if (result == Class.DoesNotExist) return null;
+ if (result != null) return result;
+ result = this.provideTypeNode(@namespace, name);
+ if (result != null)
+ {
+ nsTable[name.UniqueIdKey] = result;
+ return result;
+ }
+ nsTable[name.UniqueIdKey] = Class.DoesNotExist;
+ return null;
+ }
+ }
+ if (this.types != null && this.types.Count > this.savedTypesLength)
+ {
+ int n = this.savedTypesLength = this.types.Count;
+ for (int i = 0; i < n; i++)
+ {
+ TypeNode t = this.types[i];
+ if (t == null) continue;
+ if (t.Namespace == null) t.Namespace = Identifier.Empty;
+ nsTable = (TrivialHashtable)this.namespaceTable[t.Namespace.UniqueIdKey];
+ if (nsTable == null) this.namespaceTable[t.Namespace.UniqueIdKey] = nsTable = new TrivialHashtable();
+ nsTable[t.Name.UniqueIdKey] = t;
+ }
+ return this.GetType(@namespace, name);
+ }
+ return null;
+ }
+ protected internal TypeNodeList types;
+ /// <summary>The types contained in this module or assembly.</summary>
+ public virtual TypeNodeList Types
+ {
+ get
+ {
+ if (this.types != null) return this.types;
+ if (this.provideTypeNodeList != null)
+ {
+ lock (Module.GlobalLock)
+ {
+ if (this.types == null)
+ this.provideTypeNodeList(this);
+ }
+ }
+ else
+ this.types = new TypeNodeList();
+ return this.types;
+ }
+ set
+ {
+ this.types = value;
+ }
+ }
+#if !MinimalReader
+ protected TrivialHashtable referencedModulesAndAssemblies;
+#endif
+ public virtual bool HasReferenceTo(Module module)
+ {
+ if (module == null) return false;
+ AssemblyNode assembly = module as AssemblyNode;
+ if (assembly != null)
+ {
+ AssemblyReferenceList arefs = this.AssemblyReferences;
+ for (int i = 0, n = arefs == null ? 0 : arefs.Count; i < n; i++)
+ {
+ AssemblyReference aref = arefs[i];
+ if (aref == null) continue;
+ if (aref.Matches(assembly.Name, assembly.Version, assembly.Culture, assembly.PublicKeyToken))
+ return true;
+ }
+ }
+ if (this.ContainingAssembly != module.ContainingAssembly)
+ return false;
+ ModuleReferenceList mrefs = this.ModuleReferences;
+ for (int i = 0, n = mrefs == null ? 0 : mrefs.Count; i < n; i++)
+ {
+ //^ assert mrefs != null;
+ ModuleReference mref = mrefs[i];
+ if (mref == null || mref.Name == null) continue;
+ if (0 == PlatformHelpers.StringCompareOrdinalIgnoreCase(mref.Name, module.Name))
+ return true;
+ }
+ return false;
+ }
+ internal void InitializeAssemblyReferenceResolution(Module referringModule)
+ {
+ if (this.AssemblyReferenceResolution == null && referringModule != null)
+ {
+ this.AssemblyReferenceResolution = referringModule.AssemblyReferenceResolution;
+ this.AssemblyReferenceResolutionAfterProbingFailed = referringModule.AssemblyReferenceResolutionAfterProbingFailed;
+ }
+ }
+#if !MinimalReader
+ public static Module GetModule(byte[] buffer)
+ {
+ return Module.GetModule(buffer, null, false, false, true, false);
+ }
+ public static Module GetModule(byte[] buffer, IDictionary cache)
+ {
+ return Module.GetModule(buffer, null, false, false, false, false);
+ }
+ public static Module GetModule(byte[] buffer, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache)
+ {
+ return Module.GetModule(buffer, cache, doNotLockFile, getDebugInfo, useGlobalCache, false);
+ }
+ public static Module GetModule(byte[] buffer, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches)
+ {
+ if (buffer == null) return null;
+ return (new Reader(buffer, cache, doNotLockFile, getDebugInfo, useGlobalCache, false)).ReadModule();
+ }
+#endif
+ public static Module GetModule(string location)
+ {
+ return Module.GetModule(location, null, false, false, true, false);
+ }
+ public static Module GetModule(string location, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache)
+ {
+ return Module.GetModule(location, null, doNotLockFile, getDebugInfo, useGlobalCache, false);
+ }
+ public static Module GetModule(string location, IDictionary cache)
+ {
+ return Module.GetModule(location, cache, false, false, false, false);
+ }
+ public static Module GetModule(string location, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache)
+ {
+ return Module.GetModule(location, cache, doNotLockFile, getDebugInfo, useGlobalCache, false);
+ }
+ public static Module GetModule(string location, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches)
+ {
+ if (location == null) return null;
+ return (new Reader(location, cache, doNotLockFile, getDebugInfo, useGlobalCache, preserveShortBranches)).ReadModule();
+ }
+ public virtual AssemblyNode Resolve(AssemblyReference assemblyReference)
+ {
+ if (this.AssemblyReferenceResolution == null) return null;
+ return this.AssemblyReferenceResolution(assemblyReference, this);
+ }
+ public virtual AssemblyNode ResolveAfterProbingFailed(AssemblyReference assemblyReference)
+ {
+ if (this.AssemblyReferenceResolutionAfterProbingFailed == null) return null;
+ return this.AssemblyReferenceResolutionAfterProbingFailed(assemblyReference, this);
+ }
+#if !MinimalReader
+ public virtual void AfterAssemblyLoadProcessing()
+ {
+ if (this.AfterAssemblyLoad != null)
+ {
+ this.AfterAssemblyLoad(this as AssemblyNode);
+ }
+ }
+#endif
+#if !NoWriter
+ public virtual void WriteModule(string/*!*/ location, bool writeDebugSymbols)
+ {
+ this.Location = location;
+ Writer.WritePE(location, writeDebugSymbols, this);
+ }
+ public virtual void WriteModule(Stream/*!*/ executable, Stream debugSymbols)
+ {
+ Writer.WritePE(executable, debugSymbols, this);
+ }
+ public virtual void WriteModule(out byte[] executable)
+ {
+ Writer.WritePE(out executable, this);
+ }
+ public virtual void WriteModule(out byte[] executable, out byte[] debugSymbols)
+ {
+ Writer.WritePE(out executable, out debugSymbols, this);
+ }
+ public virtual void WriteModule(string/*!*/ location, System.CodeDom.Compiler.CompilerParameters/*!*/ options)
+ {
+ this.Location = location;
+ Writer.WritePE(options, this);
+ }
+#endif
+#if !NoXml
+ public virtual void WriteDocumentation(System.IO.TextWriter doc)
+ {
+ if (this.documentation == null) return;
+ XmlTextWriter xwriter = new XmlTextWriter(doc);
+ xwriter.Formatting = Formatting.Indented;
+ xwriter.Indentation = 2;
+ xwriter.WriteProcessingInstruction("xml", "version=\"1.0\"");
+ xwriter.WriteStartElement("doc");
+ AssemblyNode assem = this as AssemblyNode;
+ if (assem != null)
+ {
+ xwriter.WriteStartElement("assembly");
+ xwriter.WriteElementString("name", assem.Name);
+ xwriter.WriteEndElement();
+ }
+ xwriter.WriteStartElement("members");
+ TypeNodeList types = this.Types;
+ for (int i = 1, n = types == null ? 0 : types.Count; i < n; i++)
+ {
+ //^ assert types != null;
+ TypeNode t = types[i]; if (t == null) continue;
+ t.WriteDocumentation(xwriter);
+ }
+ xwriter.WriteEndElement();
+ xwriter.WriteEndElement();
+ xwriter.Close();
+ }
+#endif
+#if !NoWriter
+ public delegate MethodBodySpecializer/*!*/ MethodBodySpecializerFactory(Module/*!*/ m, TypeNodeList/*!*/ pars, TypeNodeList/*!*/ args);
+ public MethodBodySpecializerFactory CreateMethodBodySpecializer;
+ public MethodBodySpecializer/*!*/ GetMethodBodySpecializer(TypeNodeList/*!*/ pars, TypeNodeList/*!*/ args)
+ {
+ if (CreateMethodBodySpecializer != null)
+ return this.CreateMethodBodySpecializer(this, pars, args);
+ return new MethodBodySpecializer(this, pars, args);
+ }
+#endif
+ }
+ public class AssemblyNode : Module
+ { //An assembly is a module with a strong name
+#if !NoWriter
+ public string KeyContainerName;
+ public byte[] KeyBlob;
+#endif
+#if !NoReflection
+ private static Hashtable CompiledAssemblies;// so we can find in-memory compiled assemblies later (contains weak references)
+#endif
+#if !MinimalReader
+ protected AssemblyNode contractAssembly;
+ /// <summary>A separate assembly that supplied the type and method contracts for this assembly.</summary>
+ public virtual AssemblyNode ContractAssembly
+ {
+ get
+ {
+ return this.contractAssembly;
+ }
+ set
+ {
+ if (this.contractAssembly != null) { Debug.Assert(false); return; }
+ this.contractAssembly = value;
+ if (value == null) return;
+ #region Copy over any external references from the contract assembly to this one (if needed)
+ // These external references are needed only for the contract deserializer
+ AssemblyReferenceList ars = new AssemblyReferenceList();
+ AssemblyReferenceList contractReferences = value.AssemblyReferences;
+ // see if contractReferences[i] is already in the external references of "this"
+ for (int i = 0, n = contractReferences == null ? 0 : contractReferences.Count; i < n; i++)
+ {
+ //^ assert contractReferences != null;
+ AssemblyReference aref = contractReferences[i];
+ if (aref == null) continue;
+ if (aref.Assembly != this)
+ { // don't copy the contract's external reference to "this"
+ int j = 0;
+ int m = this.AssemblyReferences == null ? 0 : this.AssemblyReferences.Count;
+ while (j < m)
+ {
+ if (aref.Assembly.Name != null &&
+ this.AssemblyReferences[j].Name != null &&
+ aref.Assembly.Name.Equals(this.AssemblyReferences[j].Name))
+ break;
+ j++;
+ }
+ if (j == m)
+ { // then it wasn't found in the list of the real references
+ ars.Add(contractReferences[i]);
+ }
+ }
+ }
+ if (this.AssemblyReferences == null)
+ this.AssemblyReferences = new AssemblyReferenceList();
+ for (int i = 0, n = ars.Count; i < n; i++)
+ {
+ this.AssemblyReferences.Add(ars[i]);
+ }
+ #endregion Copy over any external references from the contract assembly to this one (if needed)
+
+#if ExtendedRuntime
+ #region Copy over any assembly-level attributes from the Contracts namespace
+ int contractsNamespaceKey = SystemTypes.NonNullType.Namespace.UniqueIdKey;
+ // Copy the assembly-level contract attributes over to the shadowed assembly.
+ foreach(AttributeNode attr in contractAssembly.Attributes) {
+ if(attr.Type != SystemTypes.ShadowsAssemblyAttribute // can't copy this one or the real assembly will be treated as a shadow assembly!
+ &&
+ attr.Type.Namespace != null && attr.Type.Namespace.UniqueIdKey == contractsNamespaceKey)
+ this.Attributes.Add(attr);
+ }
+ #endregion Copy over any assembly-level attributes from the Contracts namespace
+#endif
+
+ TypeNodeList instantiatedTypes = null;
+ if (this.reader != null) instantiatedTypes = this.reader.GetInstantiatedTypes();
+ if (instantiatedTypes != null)
+ for (int i = 0, n = instantiatedTypes.Count; i < n; i++)
+ {
+ TypeNode t = instantiatedTypes[i];
+ if (t == null) continue;
+
+ if (t.members == null)
+ {
+#if ExtendedRuntime
+ // Then will never get to ApplyOutOfBandContracts and will never have any
+ // type-level attributes copied over. So need to do this here as well as
+ // within ApplyOutOfBandContracts
+ TypeNode contractType = this.ContractAssembly.GetType(t.Namespace, t.Name);
+ if (contractType == null) continue;
+ // Copy the type-level contract attributes over to the shadowed type.
+ foreach (AttributeNode attr in contractType.Attributes) {
+ if (attr.Type.Namespace != null && attr.Type.Namespace.UniqueIdKey == contractsNamespaceKey)
+ t.Attributes.Add(attr);
+ }
+#endif
+ continue;
+ }
+#if ExtendedRuntime
+ t.ApplyOutOfBandContracts();
+#endif
+ }
+ }
+ }
+#endif
+ internal static readonly AssemblyNode/*!*/ Dummy = new AssemblyNode();
+ protected string strongName;
+ /// <summary>
+ /// A string containing the name, version, culture and key of this assembly, formatted as required by the CLR loader.
+ /// </summary>
+ public virtual string/*!*/ StrongName
+ {
+ get
+ {
+ if (this.strongName == null)
+ this.strongName = AssemblyNode.GetStrongName(this.Name, this.Version, this.Culture, this.PublicKeyOrToken, (this.Flags & AssemblyFlags.Retargetable) != 0);
+ return this.strongName;
+ }
+ }
+
+ [Obsolete("Please use GetAttribute(TypeNode attributeType)")]
+ public virtual AttributeNode GetAttributeByName(TypeNode attributeType)
+ {
+ if (attributeType == null) return null;
+ AttributeList attributes = this.Attributes;
+ for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++)
+ {
+ //^ assert attributes != null;
+ AttributeNode attr = attributes[i];
+ if (attr == null) continue;
+ MemberBinding mb = attr.Constructor as MemberBinding;
+ if (mb != null)
+ {
+ if (mb.BoundMember == null || mb.BoundMember.DeclaringType == null) continue;
+ if (mb.BoundMember.DeclaringType.FullName != attributeType.FullName) continue;
+ return attr;
+ }
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Gets the first attribute of the given type in the custom attribute list of this member. Returns null if none found.
+ /// The member is assumed to be either imported, or already in a form suitable for export.
+ /// </summary>
+ public virtual AttributeNode GetModuleAttribute(TypeNode attributeType)
+ {
+ if (attributeType == null) return null;
+ AttributeList attributes = this.ModuleAttributes;
+ for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++)
+ {
+ //^ assert attributes != null;
+ AttributeNode attr = attributes[i];
+ if (attr == null) continue;
+ MemberBinding mb = attr.Constructor as MemberBinding;
+ if (mb != null)
+ {
+ if (mb.BoundMember == null) continue;
+ if (mb.BoundMember.DeclaringType != attributeType) continue;
+ return attr;
+ }
+ Literal lit = attr.Constructor as Literal;
+ if (lit == null) continue;
+ if ((lit.Value as TypeNode) != attributeType) continue;
+ return attr;
+ }
+ return null;
+ }
+
+ public AssemblyNode()
+ : base()
+ {
+ this.NodeType = NodeType.Assembly;
+ this.ContainingAssembly = this;
+ }
+ public AssemblyNode(TypeNodeProvider provider, TypeNodeListProvider listProvider,
+ CustomAttributeProvider provideCustomAttributes, ResourceProvider provideResources, string directory)
+ : base(provider, listProvider, provideCustomAttributes, provideResources)
+ {
+ this.Directory = directory;
+ this.NodeType = NodeType.Assembly;
+ this.ContainingAssembly = this;
+ }
+ public override void Dispose()
+ {
+#if !NoReflection
+ if (this.cachedRuntimeAssembly != null)
+ this.cachedRuntimeAssembly.Dispose();
+ this.cachedRuntimeAssembly = null;
+#endif
+ lock (Reader.StaticAssemblyCache)
+ {
+ foreach (object key in new ArrayList(Reader.StaticAssemblyCache.Keys))
+ {
+ if (Reader.StaticAssemblyCache[key] == this)
+ Reader.StaticAssemblyCache.Remove(key);
+ }
+ AssemblyReference aRef = (AssemblyReference)TargetPlatform.AssemblyReferenceFor[Identifier.For(this.Name).UniqueIdKey];
+ if (aRef != null && aRef.Assembly == this)
+ {
+ aRef.Assembly = null;
+ //TODO: what about other static references to the assembly, such as SystemTypes.SystemXmlAssembly?
+ }
+ }
+ base.Dispose();
+ }
+ private string culture;
+ /// <summary>The target culture of any localized resources in this assembly.</summary>
+ public string Culture
+ {
+ get { return this.culture; }
+ set { this.culture = value; }
+ }
+ private AssemblyFlags flags;
+ /// <summary>An enumeration that identifies the what kind of assembly this is.</summary>
+ public AssemblyFlags Flags
+ {
+ get { return this.flags; }
+ set { this.flags = value; }
+ }
+ private string moduleName;
+ /// <summary>Attributes that specifically target a module rather an assembly.</summary>
+ public string ModuleName
+ { //An assembly can have a different name from the module.
+ get { return this.moduleName; }
+ set { this.moduleName = value; }
+ }
+ private byte[] publicKeyOrToken;
+ /// <summary>The public part of the key pair used to sign this assembly, or a hash of the public key.</summary>
+ public byte[] PublicKeyOrToken
+ {
+ get { return this.publicKeyOrToken; }
+ set { this.publicKeyOrToken = value; }
+ }
+ private System.Version version;
+ /// <summary>The version of this assembly.</summary>
+ public System.Version Version
+ {
+ get { return this.version; }
+ set { this.version = value; }
+ }
+ private DateTime fileLastWriteTimeUtc;
+ public DateTime FileLastWriteTimeUtc
+ {
+ get { return this.fileLastWriteTimeUtc; }
+ set { this.fileLastWriteTimeUtc = value; }
+ }
+ protected TypeNodeList exportedTypes;
+ /// <summary>
+ /// Public types defined in other modules making up this assembly and to which other assemblies may refer to.
+ /// </summary>
+ public virtual TypeNodeList ExportedTypes
+ {
+ get
+ {
+ if (this.exportedTypes != null) return this.exportedTypes;
+ if (this.provideTypeNodeList != null)
+ {
+ TypeNodeList types = this.Types; //Gets the exported types as a side-effect
+ if (types != null) types = null;
+ }
+ else
+ this.exportedTypes = new TypeNodeList();
+ return this.exportedTypes;
+ }
+ set
+ {
+ this.exportedTypes = value;
+ }
+ }
+ public bool GetDebugSymbols
+ {
+ get
+ {
+ if (this.reader == null) return false;
+ return this.reader.getDebugSymbols;
+ }
+ set
+ {
+ if (this.reader == null) return;
+ this.reader.getDebugSymbols = value;
+ }
+ }
+#if !MinimalReader
+ public static AssemblyNode GetAssembly(byte[] buffer)
+ {
+ return AssemblyNode.GetAssembly(buffer, null, false, false, true, false);
+ }
+ public static AssemblyNode GetAssembly(byte[] buffer, IDictionary cache)
+ {
+ return AssemblyNode.GetAssembly(buffer, cache, false, false, false, false);
+ }
+ public static AssemblyNode GetAssembly(byte[] buffer, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache)
+ {
+ return AssemblyNode.GetAssembly(buffer, cache, doNotLockFile, getDebugInfo, useGlobalCache, false);
+ }
+ public static AssemblyNode GetAssembly(byte[] buffer, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches)
+ {
+ if (buffer == null) return null;
+ if (CoreSystemTypes.SystemAssembly == null) Debug.Fail("");
+ return (new Reader(buffer, cache, doNotLockFile, getDebugInfo, useGlobalCache, preserveShortBranches)).ReadModule() as AssemblyNode;
+ }
+#endif
+ public static AssemblyNode GetAssembly(string location)
+ {
+ return AssemblyNode.GetAssembly(location, null, false, false, true, false);
+ }
+ public static AssemblyNode GetAssembly(string location, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache)
+ {
+ return AssemblyNode.GetAssembly(location, null, doNotLockFile, getDebugInfo, useGlobalCache, false);
+ }
+ public static AssemblyNode GetAssembly(string location, IDictionary cache)
+ {
+ return AssemblyNode.GetAssembly(location, cache, false, false, false, false);
+ }
+ public static AssemblyNode GetAssembly(string location, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache)
+ {
+ return AssemblyNode.GetAssembly(location, cache, doNotLockFile, getDebugInfo, useGlobalCache, false);
+ }
+ public static AssemblyNode GetAssembly(string location, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches)
+ {
+ if (location == null) return null;
+ if (CoreSystemTypes.SystemAssembly == null) Debug.Fail("");
+ return (new Reader(location, cache, doNotLockFile, getDebugInfo, useGlobalCache, preserveShortBranches)).ReadModule() as AssemblyNode;
+ }
+#if !MinimalReader || !NoXml || !NoData
+ public static AssemblyNode GetAssembly(AssemblyReference assemblyReference)
+ {
+ return AssemblyNode.GetAssembly(assemblyReference, null, false, false, true, false);
+ }
+ public static AssemblyNode GetAssembly(AssemblyReference assemblyReference, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache)
+ {
+ return AssemblyNode.GetAssembly(assemblyReference, null, doNotLockFile, getDebugInfo, useGlobalCache, false);
+ }
+ public static AssemblyNode GetAssembly(AssemblyReference assemblyReference, IDictionary cache)
+ {
+ return AssemblyNode.GetAssembly(assemblyReference, cache, false, false, false, false);
+ }
+ public static AssemblyNode GetAssembly(AssemblyReference assemblyReference, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache)
+ {
+ return AssemblyNode.GetAssembly(assemblyReference, cache, doNotLockFile, getDebugInfo, useGlobalCache, false);
+ }
+ public static AssemblyNode GetAssembly(AssemblyReference assemblyReference, IDictionary cache, bool doNotLockFile, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches)
+ {
+ if (assemblyReference == null) return null;
+ if (CoreSystemTypes.SystemAssembly == null) Debug.Fail("");
+ Reader reader = new Reader(cache, doNotLockFile, getDebugInfo, useGlobalCache, preserveShortBranches);
+ return assemblyReference.Assembly = reader.GetAssemblyFromReference(assemblyReference);
+ }
+#endif
+#if !NoReflection
+ public static AssemblyNode GetAssembly(System.Reflection.Assembly runtimeAssembly)
+ {
+ return AssemblyNode.GetAssembly(runtimeAssembly, null, false, true, false);
+ }
+ public static AssemblyNode GetAssembly(System.Reflection.Assembly runtimeAssembly, IDictionary cache)
+ {
+ return AssemblyNode.GetAssembly(runtimeAssembly, cache, false, false, false);
+ }
+ public static AssemblyNode GetAssembly(System.Reflection.Assembly runtimeAssembly, IDictionary cache, bool getDebugInfo, bool useGlobalCache)
+ {
+ return AssemblyNode.GetAssembly(runtimeAssembly, cache, getDebugInfo, useGlobalCache, false);
+ }
+ public static AssemblyNode GetAssembly(System.Reflection.Assembly runtimeAssembly, IDictionary cache, bool getDebugInfo, bool useGlobalCache, bool preserveShortBranches)
+ {
+ if (runtimeAssembly == null) return null;
+ if (CoreSystemTypes.SystemAssembly == null) Debug.Fail("");
+ if (runtimeAssembly.GetName().Name == "mscorlib")
+ {
+ return CoreSystemTypes.SystemAssembly;
+ }
+ if (AssemblyNode.CompiledAssemblies != null)
+ {
+ WeakReference weakRef = (WeakReference)AssemblyNode.CompiledAssemblies[runtimeAssembly];
+ if (weakRef != null)
+ {
+ AssemblyNode assem = (AssemblyNode)weakRef.Target;
+ if (assem == null) AssemblyNode.CompiledAssemblies.Remove(runtimeAssembly); //Remove the dead WeakReference
+ return assem;
+ }
+ }
+ if (runtimeAssembly.Location != null && runtimeAssembly.Location.Length > 0)
+ return AssemblyNode.GetAssembly(runtimeAssembly.Location, cache, false, getDebugInfo, useGlobalCache, preserveShortBranches);
+ //Get here for in memory assemblies that were not loaded from a known AssemblyNode
+ //Need CLR support to handle such assemblies. For now return null.
+ return null;
+ }
+#endif
+ public void SetupDebugReader(string pdbSearchPath)
+ {
+ if (this.reader == null) { Debug.Assert(false); return; }
+ this.reader.SetupDebugReader(this.Location, pdbSearchPath);
+ }
+ internal static string/*!*/ GetStrongName(string name, Version version, string culture, byte[] publicKey, bool retargetable)
+ {
+ if (version == null) version = new Version();
+ StringBuilder result = new StringBuilder();
+ result.Append(name);
+ result.Append(", Version="); result.Append(version.ToString());
+ result.Append(", Culture="); result.Append(((culture == null || culture.Length == 0) ? "neutral" : culture));
+ result.Append(AssemblyNode.GetKeyString(publicKey));
+ if (retargetable)
+ result.Append(", Retargetable=Yes");
+ return result.ToString();
+ }
+ private System.Reflection.AssemblyName assemblyName;
+ public System.Reflection.AssemblyName GetAssemblyName()
+ {
+ if (this.assemblyName == null)
+ {
+ System.Reflection.AssemblyName aName = new System.Reflection.AssemblyName();
+ if (this.Location != null && this.Location != "unknown:location")
+ {
+ StringBuilder sb = new StringBuilder("file:///");
+ sb.Append(Path.GetFullPath(this.Location));
+ sb.Replace('\\', '/');
+ aName.CodeBase = sb.ToString();
+ }
+ aName.CultureInfo = new System.Globalization.CultureInfo(this.Culture);
+ if (this.PublicKeyOrToken != null && this.PublicKeyOrToken.Length > 8)
+ aName.Flags = System.Reflection.AssemblyNameFlags.PublicKey;
+ if ((this.Flags & AssemblyFlags.Retargetable) != 0)
+ aName.Flags |= (System.Reflection.AssemblyNameFlags)AssemblyFlags.Retargetable;
+ aName.HashAlgorithm = (System.Configuration.Assemblies.AssemblyHashAlgorithm)this.HashAlgorithm;
+ if (this.PublicKeyOrToken != null && this.PublicKeyOrToken.Length > 0)
+ aName.SetPublicKey(this.PublicKeyOrToken);
+ else
+ aName.SetPublicKey(new byte[0]);
+ aName.Name = this.Name;
+ aName.Version = this.Version;
+ switch (this.Flags & AssemblyFlags.CompatibilityMask)
+ {
+ case AssemblyFlags.NonSideBySideCompatible:
+ aName.VersionCompatibility = System.Configuration.Assemblies.AssemblyVersionCompatibility.SameDomain;
+ break;
+ case AssemblyFlags.NonSideBySideProcess:
+ aName.VersionCompatibility = System.Configuration.Assemblies.AssemblyVersionCompatibility.SameProcess;
+ break;
+ case AssemblyFlags.NonSideBySideMachine:
+ aName.VersionCompatibility = System.Configuration.Assemblies.AssemblyVersionCompatibility.SameMachine;
+ break;
+ }
+ this.assemblyName = aName;
+ }
+ return this.assemblyName;
+ }
+#if !NoReflection
+ private sealed class CachedRuntimeAssembly : IDisposable
+ {
+ internal System.Reflection.Assembly Value;
+ internal CachedRuntimeAssembly(System.Reflection.Assembly assembly)
+ {
+ this.Value = assembly;
+ }
+ ~CachedRuntimeAssembly()
+ {
+ this.Dispose();
+ }
+ public void Dispose()
+ {
+ if (this.Value != null)
+ {
+ if (AssemblyNode.CompiledAssemblies != null)
+ AssemblyNode.CompiledAssemblies.Remove(this.Value);
+ }
+ this.Value = null;
+ GC.SuppressFinalize(this);
+ }
+ }
+ private CachedRuntimeAssembly cachedRuntimeAssembly;
+ public System.Reflection.Assembly GetRuntimeAssembly()
+ {
+ return this.GetRuntimeAssembly(null, null);
+ }
+#endif
+#if !NoReflection
+ public System.Reflection.Assembly GetRuntimeAssembly(System.Security.Policy.Evidence evidence)
+ {
+ return this.GetRuntimeAssembly(evidence, null);
+ }
+ public System.Reflection.Assembly GetRuntimeAssembly(AppDomain targetAppDomain)
+ {
+ return this.GetRuntimeAssembly(null, targetAppDomain);
+ }
+ public System.Reflection.Assembly GetRuntimeAssembly(System.Security.Policy.Evidence evidence, AppDomain targetAppDomain)
+ {
+ System.Reflection.Assembly result = this.cachedRuntimeAssembly == null ? null : this.cachedRuntimeAssembly.Value;
+ if (result == null || evidence != null || targetAppDomain != null)
+ {
+ lock (this)
+ {
+ if (this.cachedRuntimeAssembly != null && evidence == null && targetAppDomain == null) return this.cachedRuntimeAssembly.Value;
+ if (targetAppDomain == null) targetAppDomain = AppDomain.CurrentDomain;
+ if (this.Location != null)
+ {
+ string name = this.StrongName;
+ System.Reflection.Assembly[] alreadyLoadedAssemblies = targetAppDomain.GetAssemblies();
+ if (alreadyLoadedAssemblies != null)
+ for (int i = 0, n = alreadyLoadedAssemblies.Length; i < n; i++)
+ {
+ System.Reflection.Assembly a = alreadyLoadedAssemblies[i];
+ if (a == null) continue;
+ if (a.FullName == name)
+ {
+ result = a; break;
+ }
+ }
+ if (result == null)
+ {
+ if (evidence != null)
+ result = targetAppDomain.Load(this.GetAssemblyName(), evidence);
+ else
+ result = targetAppDomain.Load(this.GetAssemblyName());
+ }
+ }
+#if !NoWriter
+ // without the writer, it is impossible to get the runtime
+ // assembly for an AssemblyNode which does not correspond
+ // to a file on disk, we will return null in that case.
+ else
+ {
+ byte[] executable = null;
+ byte[] debugSymbols = null;
+ if ((this.Flags & (AssemblyFlags.EnableJITcompileTracking | AssemblyFlags.DisableJITcompileOptimizer)) != 0)
+ {
+ this.WriteModule(out executable, out debugSymbols);
+ if (evidence != null)
+ result = targetAppDomain.Load(executable, debugSymbols, evidence);
+ else
+ result = targetAppDomain.Load(executable, debugSymbols);
+ }
+ else
+ {
+ this.WriteModule(out executable);
+ if (evidence != null)
+ result = targetAppDomain.Load(executable, null, evidence);
+ else
+ result = targetAppDomain.Load(executable);
+ }
+ }
+#endif
+ if (result != null && evidence == null && targetAppDomain == AppDomain.CurrentDomain)
+ {
+ this.AddCachedAssembly(result);
+ this.cachedRuntimeAssembly = new CachedRuntimeAssembly(result);
+ }
+ }
+ }
+ return result;
+ }
+ private void AddCachedAssembly(System.Reflection.Assembly/*!*/ runtimeAssembly)
+ {
+ if (AssemblyNode.CompiledAssemblies == null)
+ AssemblyNode.CompiledAssemblies = Hashtable.Synchronized(new Hashtable());
+ AssemblyNode.CompiledAssemblies[runtimeAssembly] = new WeakReference(this);
+ }
+#endif
+ private static string GetKeyString(byte[] publicKey)
+ {
+ if (publicKey == null) return null;
+ int n = publicKey.Length;
+ StringBuilder str;
+ if (n > 8)
+ {
+#if !ROTOR
+ System.Security.Cryptography.SHA1 sha1 = new System.Security.Cryptography.SHA1CryptoServiceProvider();
+ publicKey = sha1.ComputeHash(publicKey);
+ byte[] token = new byte[8];
+ for (int i = 0, m = publicKey.Length - 1; i < 8; i++)
+ token[i] = publicKey[m - i];
+ publicKey = token;
+ n = 8;
+#else
+ n = 0; //TODO: figure out how to compute the token on ROTOR
+#endif
+ }
+ if (n == 0)
+ str = new StringBuilder(", PublicKeyToken=null");
+ else
+ str = new StringBuilder(", PublicKeyToken=", n * 2 + 17);
+ for (int i = 0; i < n; i++)
+ str.Append(publicKey[i].ToString("x2"));
+ return str.ToString();
+ }
+ protected TrivialHashtable friends;
+ public virtual bool MayAccessInternalTypesOf(AssemblyNode assembly)
+ {
+ if (this == assembly) return true;
+ if (assembly == null || SystemTypes.InternalsVisibleToAttribute == null) return false;
+ if (this.friends == null) this.friends = new TrivialHashtable();
+ object ob = this.friends[assembly.UniqueKey];
+ if (ob == (object)string.Empty) return false;
+ if (ob == this) return true;
+ AttributeList attributes = assembly.Attributes;
+ for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++)
+ {
+ //^ assert attributes != null;
+ AttributeNode attr = attributes[i];
+ if (attr == null) continue;
+ MemberBinding mb = attr.Constructor as MemberBinding;
+ if (mb != null)
+ {
+ if (mb.BoundMember == null) continue;
+ if (mb.BoundMember.DeclaringType != SystemTypes.InternalsVisibleToAttribute) continue;
+ }
+ else
+ {
+ Literal lit = attr.Constructor as Literal;
+ if (lit == null) continue;
+ if ((lit.Value as TypeNode) != SystemTypes.InternalsVisibleToAttribute) continue;
+ }
+ if (attr.Expressions == null || attr.Expressions.Count < 1) continue;
+ Literal argLit = attr.Expressions[0] as Literal;
+ if (argLit == null) continue;
+ string friendName = argLit.Value as string;
+ if (friendName == null) continue;
+ try
+ {
+ AssemblyReference ar = new AssemblyReference(friendName);
+ byte[] tok = ar.PublicKeyToken;
+ if (tok != null && this.PublicKeyOrToken != null) tok = this.PublicKeyToken;
+ if (!ar.Matches(this.Name, ar.Version, ar.Culture, tok)) continue;
+#if !FxCop
+ }
+ catch (ArgumentException e)
+ {
+ if (this.MetadataImportErrors == null) this.MetadataImportErrors = new ArrayList();
+ this.MetadataImportErrors.Add(e.Message);
+ continue;
+ }
+#else
+ }finally{}
+#endif
+ this.friends[assembly.UniqueKey] = this;
+ return true;
+ }
+ this.friends[assembly.UniqueKey] = string.Empty;
+ return false;
+ }
+ public AssemblyReferenceList GetFriendAssemblies()
+ {
+ if (SystemTypes.InternalsVisibleToAttribute == null) return null;
+ AttributeList attributes = this.Attributes;
+ if (attributes == null) return null;
+ int n = attributes.Count; if (n == 0) return null;
+ AssemblyReferenceList result = new AssemblyReferenceList(n);
+ for (int i = 0; i < n; i++)
+ {
+ AttributeNode attr = attributes[i];
+ if (attr == null) continue;
+ MemberBinding mb = attr.Constructor as MemberBinding;
+ if (mb != null)
+ {
+ if (mb.BoundMember == null) continue;
+ if (mb.BoundMember.DeclaringType != SystemTypes.InternalsVisibleToAttribute) continue;
+ }
+ else
+ {
+ Literal lit = attr.Constructor as Literal;
+ if (lit == null) continue;
+ if ((lit.Value as TypeNode) != SystemTypes.InternalsVisibleToAttribute) continue;
+ }
+ if (attr.Expressions == null || attr.Expressions.Count < 1) continue;
+ Literal argLit = attr.Expressions[0] as Literal;
+ if (argLit == null) continue;
+ string friendName = argLit.Value as string;
+ if (friendName == null) continue;
+ result.Add(new AssemblyReference(friendName));
+ }
+ return result;
+ }
+ /// <summary>
+ /// The attributes associated with this module. This corresponds to C# custom attributes with the module target specifier.
+ /// </summary>
+ public virtual AttributeList ModuleAttributes
+ {
+ get
+ {
+ if (this.moduleAttributes != null) return this.moduleAttributes;
+ if (this.provideCustomAttributes != null)
+ {
+ lock (Module.GlobalLock)
+ {
+ if (this.moduleAttributes == null)
+ this.provideCustomAttributes(this);
+ }
+ }
+ else
+ this.moduleAttributes = new AttributeList();
+ return this.moduleAttributes;
+ }
+ set
+ {
+ this.moduleAttributes = value;
+ }
+ }
+ protected AttributeList moduleAttributes;
+
+ protected byte[] token;
+ public virtual byte[] PublicKeyToken
+ {
+ get
+ {
+ if (this.token != null) return this.token;
+ if (this.PublicKeyOrToken == null || this.PublicKeyOrToken.Length == 0) return null;
+ if (this.PublicKeyOrToken.Length == 8) return this.token = this.PublicKeyOrToken;
+#if !ROTOR
+ System.Security.Cryptography.SHA1 sha1 = new System.Security.Cryptography.SHA1CryptoServiceProvider();
+ byte[] hashedKey = sha1.ComputeHash(this.PublicKeyOrToken);
+ byte[] token = new byte[8];
+ for (int i = 0, n = hashedKey.Length - 1; i < 8; i++) token[i] = hashedKey[n - i];
+ return this.token = token;
+#else
+ return null;
+#endif
+ }
+ }
+#if !MinimalReader
+ public override string ToString()
+ {
+ return this.Name;
+ }
+#endif
+ }
+ public class AssemblyReference : Node
+ {
+#if !MinimalReader
+ public IdentifierList Aliases;
+#endif
+ private byte[] token;
+ internal Reader Reader;
+ public AssemblyReference()
+ : base(NodeType.AssemblyReference)
+ {
+ }
+ public AssemblyReference(AssemblyNode/*!*/ assembly)
+ : base(NodeType.AssemblyReference)
+ {
+ this.culture = assembly.Culture;
+ this.flags = assembly.Flags & ~AssemblyFlags.PublicKey;
+ this.hashValue = assembly.HashValue;
+ this.name = assembly.Name;
+ this.publicKeyOrToken = assembly.PublicKeyOrToken;
+ if (assembly.PublicKeyOrToken != null && assembly.PublicKeyOrToken.Length > 8)
+ this.flags |= AssemblyFlags.PublicKey;
+ this.location = assembly.Location;
+ this.version = assembly.Version;
+ this.assembly = assembly;
+ }
+#if !MinimalReader
+ public AssemblyReference(string assemblyStrongName, SourceContext sctx)
+ : this(assemblyStrongName)
+ {
+ this.SourceContext = sctx;
+ }
+#endif
+ public AssemblyReference(string assemblyStrongName)
+ : base(NodeType.AssemblyReference)
+ {
+ AssemblyFlags flags = AssemblyFlags.None;
+ if (assemblyStrongName == null) { Debug.Assert(false); assemblyStrongName = ""; }
+ int i = 0, n = assemblyStrongName.Length;
+ string name = ParseToken(assemblyStrongName, ref i);
+ string version = null;
+ string culture = null;
+ string token = null;
+ while (i < n)
+ {
+ if (assemblyStrongName[i] != ',') throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
+ ExceptionStrings.InvalidAssemblyStrongName, assemblyStrongName), "assemblyStrongName");
+ i++;
+ while (i < n && char.IsWhiteSpace(assemblyStrongName[i])) i++;
+ switch (assemblyStrongName[i])
+ {
+ case 'v':
+ case 'V': version = ParseAssignment(assemblyStrongName, "Version", ref i); break;
+ case 'c':
+ case 'C': culture = ParseAssignment(assemblyStrongName, "Culture", ref i); break;
+ case 'p':
+ case 'P':
+ if (PlatformHelpers.StringCompareOrdinalIgnoreCase(assemblyStrongName, i, "PublicKeyToken", 0, "PublicKeyToken".Length) == 0)
+ token = ParseAssignment(assemblyStrongName, "PublicKeyToken", ref i);
+ else
+ {
+ token = ParseAssignment(assemblyStrongName, "PublicKey", ref i);
+ flags |= AssemblyFlags.PublicKey;
+ }
+ break;
+ case 'r':
+ case 'R':
+ string yesOrNo = ParseAssignment(assemblyStrongName, "Retargetable", ref i);
+ if (PlatformHelpers.StringCompareOrdinalIgnoreCase(yesOrNo, "Yes") == 0)
+ flags |= AssemblyFlags.Retargetable;
+ break;
+ }
+ while (i < n && assemblyStrongName[i] == ']') i++;
+ }
+ while (i < n && char.IsWhiteSpace(assemblyStrongName[i])) i++;
+ if (i < n) throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
+ ExceptionStrings.InvalidAssemblyStrongName, assemblyStrongName), "assemblyStrongName");
+ if (PlatformHelpers.StringCompareOrdinalIgnoreCase(culture, "neutral") == 0)
+ culture = null;
+ if (PlatformHelpers.StringCompareOrdinalIgnoreCase(token, "null") == 0)
+ token = null;
+ byte[] tok = null;
+ if (token != null && (n = token.Length) > 0)
+ {
+ if (n > 16)
+ {
+ ArrayList tokArr = new ArrayList();
+ if (n % 2 == 1)
+ {
+ tokArr.Add(byte.Parse(token.Substring(0, 1), System.Globalization.NumberStyles.HexNumber, null));
+ n--;
+ }
+ for (i = 0; i < n; i += 2)
+ {
+#if WHIDBEY
+ byte b = 0;
+ bool goodByte = byte.TryParse(token.Substring(i, 2), System.Globalization.NumberStyles.HexNumber, null, out b);
+ Debug.Assert(goodByte);
+#else
+ byte b = byte.Parse(token.Substring(i, 2), System.Globalization.NumberStyles.HexNumber, null);
+#endif
+ tokArr.Add(b);
+ }
+ tok = (byte[])tokArr.ToArray(typeof(byte));
+ }
+ else
+ {
+ ulong tk = ulong.Parse(token, System.Globalization.NumberStyles.HexNumber, null);
+ tok = new byte[8];
+ tok[0] = (byte)(tk >> 56);
+ tok[1] = (byte)(tk >> 48);
+ tok[2] = (byte)(tk >> 40);
+ tok[3] = (byte)(tk >> 32);
+ tok[4] = (byte)(tk >> 24);
+ tok[5] = (byte)(tk >> 16);
+ tok[6] = (byte)(tk >> 8);
+ tok[7] = (byte)tk;
+ }
+ }
+ this.culture = culture;
+ this.name = name;
+ this.publicKeyOrToken = tok;
+ this.version = version == null || version.Length == 0 ? null : new Version(version);
+ this.flags = flags;
+ }
+ private static string ParseToken(string/*!*/ assemblyStrongName, ref int i)
+ {
+ Debug.Assert(assemblyStrongName != null);
+ int n = assemblyStrongName.Length;
+ Debug.Assert(0 <= i && i < n);
+ while (i < n && char.IsWhiteSpace(assemblyStrongName[i])) i++;
+ StringBuilder sb = new StringBuilder(n);
+ while (i < n)
+ {
+ char ch = assemblyStrongName[i];
+ if (ch == ',' || ch == ']' || char.IsWhiteSpace(ch)) break;
+ sb.Append(ch);
+ i++;
+ }
+ while (i < n && char.IsWhiteSpace(assemblyStrongName[i])) i++;
+ return sb.ToString();
+ }
+ private static string ParseAssignment(string/*!*/ assemblyStrongName, string/*!*/ target, ref int i)
+ {
+ Debug.Assert(assemblyStrongName != null && target != null);
+ int n = assemblyStrongName.Length;
+ Debug.Assert(0 < i && i < n);
+ if (PlatformHelpers.StringCompareOrdinalIgnoreCase(assemblyStrongName, i, target, 0, target.Length) != 0)
+ goto throwError;
+ i += target.Length;
+ while (i < n && char.IsWhiteSpace(assemblyStrongName[i])) i++;
+ if (i >= n || assemblyStrongName[i] != '=') goto throwError;
+ i++;
+ if (i >= n) goto throwError;
+ return ParseToken(assemblyStrongName, ref i);
+ throwError:
+ throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
+ ExceptionStrings.InvalidAssemblyStrongName, assemblyStrongName), "assemblyStrongName");
+ }
+ private string culture;
+ public string Culture
+ {
+ get { return this.culture; }
+ set { this.culture = value; }
+ }
+ private AssemblyFlags flags;
+ public AssemblyFlags Flags
+ {
+ get { return this.flags; }
+ set { this.flags = value; }
+ }
+ private byte[] hashValue;
+ public byte[] HashValue
+ {
+ get { return this.hashValue; }
+ set { this.hashValue = value; }
+ }
+ private string name;
+ public string Name
+ {
+ get { return this.name; }
+ set { this.name = value; }
+ }
+ private byte[] publicKeyOrToken;
+ public byte[] PublicKeyOrToken
+ {
+ get { return this.publicKeyOrToken; }
+ set { this.publicKeyOrToken = value; }
+ }
+ private System.Version version;
+ public System.Version Version
+ {
+ get { return this.version; }
+ set { this.version = value; }
+ }
+ private string location;
+ public string Location
+ {
+ get { return this.location; }
+ set { this.location = value; }
+ }
+ protected internal AssemblyNode assembly;
+ public virtual AssemblyNode Assembly
+ {
+ get
+ {
+ if (this.assembly != null) return this.assembly;
+ if (this.Reader != null)
+ return this.assembly = this.Reader.GetAssemblyFromReference(this);
+ return null;
+ }
+ set
+ {
+ this.assembly = value;
+ }
+ }
+ protected string strongName;
+ public virtual string StrongName
+ {
+ get
+ {
+ if (this.strongName == null)
+ this.strongName = AssemblyNode.GetStrongName(this.Name, this.Version, this.Culture, this.PublicKeyOrToken, (this.Flags & AssemblyFlags.Retargetable) != 0);
+ return this.strongName;
+ }
+ }
+ private System.Reflection.AssemblyName assemblyName;
+ public System.Reflection.AssemblyName GetAssemblyName()
+ {
+ if (this.assemblyName == null)
+ {
+ System.Reflection.AssemblyName aName = new System.Reflection.AssemblyName();
+ aName.CultureInfo = new System.Globalization.CultureInfo(this.Culture == null ? "" : this.Culture);
+ if (this.PublicKeyOrToken != null && this.PublicKeyOrToken.Length > 8)
+ aName.Flags = System.Reflection.AssemblyNameFlags.PublicKey;
+ if ((this.Flags & AssemblyFlags.Retargetable) != 0)
+ aName.Flags |= (System.Reflection.AssemblyNameFlags)AssemblyFlags.Retargetable;
+ aName.HashAlgorithm = System.Configuration.Assemblies.AssemblyHashAlgorithm.SHA1;
+ if (this.PublicKeyOrToken != null)
+ {
+ if (this.PublicKeyOrToken.Length > 8)
+ aName.SetPublicKey(this.PublicKeyOrToken);
+ else if (this.PublicKeyOrToken.Length > 0)
+ aName.SetPublicKeyToken(this.PublicKeyOrToken);
+ }
+ else
+ aName.SetPublicKey(new byte[0]);
+ aName.Name = this.Name;
+ aName.Version = this.Version;
+ switch (this.Flags & AssemblyFlags.CompatibilityMask)
+ {
+ case AssemblyFlags.NonSideBySideCompatible:
+ aName.VersionCompatibility = System.Configuration.Assemblies.AssemblyVersionCompatibility.SameDomain;
+ break;
+ case AssemblyFlags.NonSideBySideProcess:
+ aName.VersionCompatibility = System.Configuration.Assemblies.AssemblyVersionCompatibility.SameProcess;
+ break;
+ case AssemblyFlags.NonSideBySideMachine:
+ aName.VersionCompatibility = System.Configuration.Assemblies.AssemblyVersionCompatibility.SameMachine;
+ break;
+ }
+ this.assemblyName = aName;
+ }
+ return this.assemblyName;
+ }
+ public bool Matches(string name, Version version, string culture, byte[] publicKeyToken)
+ {
+ if (culture != null && culture.Length == 0) culture = null;
+ if (this.Culture != null && this.Culture.Length == 0) this.Culture = null;
+ if (this.Version != version && this.Version != null && (version == null || !this.Version.Equals(version))) return false;
+ if (PlatformHelpers.StringCompareOrdinalIgnoreCase(this.Name, name) != 0 ||
+ PlatformHelpers.StringCompareOrdinalIgnoreCase(this.Culture, culture) != 0) return false;
+ if ((this.Flags & AssemblyFlags.Retargetable) != 0) return true;
+ byte[] thisToken = this.PublicKeyToken;
+ if (publicKeyToken == null) return thisToken == null;
+ if (thisToken == publicKeyToken) return true;
+ if (thisToken == null) return false;
+ int n = publicKeyToken.Length;
+ if (n != thisToken.Length) return false;
+ for (int i = 0; i < n; i++) if (thisToken[i] != publicKeyToken[i]) return false;
+ return true;
+ }
+ public bool MatchesIgnoringVersion(AssemblyReference reference)
+ {
+ if (reference == null) return false;
+ return this.Matches(reference.Name, this.Version, reference.Culture, reference.PublicKeyToken);
+ }
+ public byte[] PublicKeyToken
+ {
+ get
+ {
+ if (this.token != null) return this.token;
+ if (this.PublicKeyOrToken == null || this.PublicKeyOrToken.Length == 0) return null;
+ if (this.PublicKeyOrToken.Length == 8) return this.token = this.PublicKeyOrToken;
+#if !ROTOR
+ System.Security.Cryptography.SHA1 sha = new System.Security.Cryptography.SHA1CryptoServiceProvider();
+ byte[] hashedKey = sha.ComputeHash(this.PublicKeyOrToken);
+ byte[] token = new byte[8];
+ for (int i = 0, n = hashedKey.Length - 1; i < 8; i++) token[i] = hashedKey[n - i];
+ return this.token = token;
+#else
+ return null;
+#endif
+ }
+ }
+ }
+ public class ModuleReference : Node
+ {
+ private Module module;
+ private string name;
+ public ModuleReference()
+ : base(NodeType.ModuleReference)
+ {
+ }
+ public ModuleReference(string name, Module module)
+ : base(NodeType.ModuleReference)
+ {
+ this.name = name;
+ this.module = module;
+ }
+ public Module Module
+ {
+ get { return this.module; }
+ set { this.module = value; }
+ }
+ public string Name
+ {
+ get { return this.name; }
+ set { this.name = value; }
+ }
+ }
+ /// <summary>
+ /// A member of a Namespace or a TypeNode
+ /// </summary>
+ public abstract class Member : Node
+ {
+#if !MinimalReader
+ /// <summary>The namespace of which this node is a member. Null if this node is a member of type.</summary>
+ public Namespace DeclaringNamespace;
+ /// <summary>
+ /// Indicates that the signature of this member may include unsafe types such as pointers. For methods and properties, it also indicates that the
+ /// code may contain unsafe constructions such as pointer arithmetic.
+ /// </summary>
+ public bool IsUnsafe;
+ /// <summary>A list of other nodes that refer to this member. Must be filled in by client code.</summary>
+ public NodeList References;
+#endif
+ protected Member(NodeType nodeType)
+ : base(nodeType)
+ {
+ }
+ protected Member(TypeNode declaringType, AttributeList attributes, Identifier name, NodeType nodeType)
+ : base(nodeType)
+ {
+ this.attributes = attributes;
+ this.declaringType = declaringType;
+ this.name = name;
+ }
+ private TypeNode declaringType;
+ /// <summary>The type of which this node is a member. Null if this node is a member of a Namespace.</summary>
+ public TypeNode DeclaringType
+ {
+ get { return this.declaringType; }
+ set { this.declaringType = value; }
+ }
+ private Identifier name;
+ /// <summary>The unqualified name of the member.</summary>
+ public Identifier Name
+ {
+ get { return this.name; }
+ set { this.name = value; }
+ }
+#if ExtendedRuntime
+ private Anonymity anonymity;
+#endif
+ protected AttributeList attributes;
+ private bool notObsolete;
+ private ObsoleteAttribute obsoleteAttribute;
+
+ /// <summary>
+ /// The attributes of this member. Corresponds to custom attribute annotations in C#.
+ /// </summary>
+ public virtual AttributeList Attributes
+ {
+ get
+ {
+ if (this.attributes != null) return this.attributes;
+ return this.attributes = new AttributeList();
+ }
+ set
+ {
+ this.attributes = value;
+ }
+ }
+ protected Member hiddenMember;
+ public virtual Member HiddenMember
+ {
+ get
+ {
+ return this.hiddenMember;
+ }
+ set
+ {
+ this.hiddenMember = value;
+ }
+ }
+ protected bool hidesBaseClassMemberSpecifiedExplicitly;
+ protected bool hidesBaseClassMember;
+ /// <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>
+ public bool HidesBaseClassMember
+ {
+ get
+ {
+ if (this.hidesBaseClassMemberSpecifiedExplicitly)
+ return this.hidesBaseClassMember;
+ else
+ return this.HiddenMember != null;
+ }
+ set
+ {
+ this.hidesBaseClassMember = value;
+ this.hidesBaseClassMemberSpecifiedExplicitly = true;
+ }
+ }
+ protected Member overriddenMember;
+ public virtual Member OverriddenMember
+ {
+ get
+ {
+ return this.overriddenMember;
+ }
+ set
+ {
+ this.overriddenMember = value;
+ }
+ }
+ protected bool overridesBaseClassMemberSpecifiedExplicitly;
+ protected bool overridesBaseClassMember;
+ /// <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>
+ public virtual bool OverridesBaseClassMember
+ {
+ get
+ {
+ if (this.overridesBaseClassMemberSpecifiedExplicitly)
+ return this.overridesBaseClassMember;
+ else
+ return this.OverriddenMember != null;
+ }
+ set
+ {
+ this.overridesBaseClassMember = value;
+ this.overridesBaseClassMemberSpecifiedExplicitly = true;
+ }
+ }
+ /// <summary>
+ /// Gets the first attribute of the given type in the attribute list of this member. Returns null if none found.
+ /// This should not be called until the AST containing this member has been processed to replace symbolic references
+ /// to members with references to the actual members.
+ /// </summary>
+ public virtual AttributeNode GetAttribute(TypeNode attributeType)
+ {
+ if (attributeType == null) return null;
+ AttributeList attributes = this.Attributes;
+ for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++)
+ {
+ AttributeNode attr = attributes[i];
+ if (attr == null) continue;
+ MemberBinding mb = attr.Constructor as MemberBinding;
+ if (mb != null)
+ {
+ if (mb.BoundMember == null) continue;
+ if (mb.BoundMember.DeclaringType != attributeType) continue;
+ return attr;
+ }
+ Literal lit = attr.Constructor as Literal;
+ if (lit == null) continue;
+ if ((lit.Value as TypeNode) != attributeType) continue;
+ return attr;
+ }
+ return null;
+ }
+ public virtual AttributeList GetFilteredAttributes(TypeNode attributeType)
+ {
+ if (attributeType == null) return this.Attributes;
+ AttributeList attributes = this.Attributes;
+ AttributeList filtered = new AttributeList();
+ for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++)
+ {
+ AttributeNode attr = attributes[i];
+ if (attr == null) continue;
+ MemberBinding mb = attr.Constructor as MemberBinding;
+ if (mb != null)
+ {
+ if (mb.BoundMember != null && mb.BoundMember.DeclaringType == attributeType) continue;
+ filtered.Add(attr);
+ continue;
+ }
+ Literal lit = attr.Constructor as Literal;
+ if (lit != null && (lit.Value as TypeNode) == attributeType) continue;
+ filtered.Add(attr);
+ }
+ return filtered;
+ }
+#if ExtendedRuntime
+ /// <summary>
+ /// If this is true, the name of the member is meaningless and the member is intended as an "invisible" container for other members.
+ /// The value of this property is controlled by the presence or absence of the Anonymous attribute.
+ /// </summary>
+ public bool IsAnonymous{
+ get{
+ switch (this.Anonymity){
+ case Anonymity.None:
+ case Anonymity.Unknown:
+ return false;
+ default:
+ return true;
+ }
+ }
+ }
+ /// <summary>
+ /// Exposes the value of the Anonymous attribute. The value is Anonimity.None if no attribute is present.
+ /// </summary>
+ public Anonymity Anonymity{
+ get{
+ if (this.anonymity == Anonymity.Unknown){
+ AttributeNode attr = this.GetAttribute(SystemTypes.AnonymousAttribute);
+ if (attr == null)
+ this.anonymity = Anonymity.None;
+ else{
+ this.anonymity = Anonymity.Structural; // default
+ if (attr.Expressions != null){
+ for (int i = 0, n = attr.Expressions.Count; i < n; i++){
+ NamedArgument na = attr.Expressions[i] as NamedArgument;
+ if (na == null || na.Name != null) continue;
+ if (na.Name.UniqueIdKey == StandardIds.Anonymity.UniqueIdKey){
+ Literal lit = na.Value as Literal;
+ if (lit == null) continue;
+ this.anonymity = (Anonymity)lit.Value;
+ break;
+ }
+ }
+ }
+ }
+ }
+ return this.anonymity;
+ }
+ }
+ CciMemberKind cciKind;
+ public CciMemberKind CciKind{
+ get{
+ if (cciKind == CciMemberKind.Unknown){
+ AttributeNode a = GetAttribute(SystemTypes.CciMemberKindAttribute);
+ if (a == null)
+ cciKind = CciMemberKind.Regular;
+ else
+ cciKind = (CciMemberKind) ((Literal) a.Expressions[0]).Value;
+ }
+ return cciKind;
+ }
+ set{
+ this.cciKind = value;
+ }
+ }
+#endif
+ /// <summary>
+ /// The concatenation of the FullName of the containing member and the name of this member.
+ /// Separated with a '.' character if the containing member is a namespace and a '+' character if the containing member is a Type.
+ /// Includes the parameter type full names when this member is a method or a property. Also includes (generic) template arguments.
+ /// </summary>
+ public abstract string/*!*/ FullName { get; }
+ /// <summary>True if all references to this member must be from the assembly containing the definition of this member. </summary>
+ public abstract bool IsAssembly { get; }
+ /// <summary>
+ /// True if access to this member is controlled by the compiler and not the runtime. Cannot be accessed from other assemblies since these
+ /// are not necessarily controlled by the same compiler.
+ /// </summary>
+ public abstract bool IsCompilerControlled { get; }
+ /// <summary>True if this member can only be accessed from subclasses of the class declaring this member.</summary>
+ public abstract bool IsFamily { get; }
+ /// <summary>True if this member can only be accessed from subclasses of the class declaring this member, provided that these subclasses are also
+ /// contained in the assembly containing this member.</summary>
+ public abstract bool IsFamilyAndAssembly { get; }
+ /// <summary>True if all references to this member must either be from the assembly containing the definition of this member,
+ /// or from a subclass of the class declaring this member.</summary>
+ public abstract bool IsFamilyOrAssembly { get; }
+ /// <summary>True if all references to this member must be from members of the type declaring this member./// </summary>
+ public abstract bool IsPrivate { get; }
+ /// <summary>True if the member can be accessed from anywhere./// </summary>
+ public abstract bool IsPublic { get; }
+ /// <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>
+ public abstract bool IsSpecialName { get; }
+ /// <summary>True if this member always has the same value or behavior for all instances the declaring type.</summary>
+ public abstract bool IsStatic { get; }
+ /// <summary>True if another assembly can contain a reference to this member.</summary>
+ public abstract bool IsVisibleOutsideAssembly { get; }
+ /// <summary>A cached reference to the first Obsolete attribute of this member. Null if no such attribute exsits.</summary>
+ public ObsoleteAttribute ObsoleteAttribute
+ {
+ get
+ {
+ if (this.notObsolete) return null;
+ if (this.obsoleteAttribute == null)
+ {
+ AttributeNode attr = this.GetAttribute(SystemTypes.ObsoleteAttribute);
+ if (attr != null)
+ {
+ ExpressionList args = attr.Expressions;
+ int numArgs = args == null ? 0 : args.Count;
+ Literal lit0 = numArgs > 0 ? args[0] as Literal : null;
+ Literal lit1 = numArgs > 1 ? args[1] as Literal : null;
+ string message = lit0 != null ? lit0.Value as string : null;
+ object isError = lit1 != null ? lit1.Value : null;
+ if (isError is bool)
+ return this.obsoleteAttribute = new ObsoleteAttribute(message, (bool)isError);
+ else
+ return this.obsoleteAttribute = new ObsoleteAttribute(message);
+ }
+ this.notObsolete = true;
+ }
+ return this.obsoleteAttribute;
+ }
+ set
+ {
+ this.obsoleteAttribute = value;
+ this.notObsolete = false;
+ }
+ }
+#if !MinimalReader
+ /// <summary>The source code, if any, corresponding to the value in Documentation.</summary>
+ public Node DocumentationNode;
+#endif
+#if !NoXml
+ protected XmlNode documentation;
+ /// <summary>The body of an XML element containing a description of this member. Used to associated documentation (such as this comment) with members.
+ /// The fragment usually conforms to the structure defined in the C# standard.</summary>
+ public virtual XmlNode Documentation
+ {
+ get
+ {
+ XmlNode documentation = this.documentation;
+ if (documentation != null) return documentation;
+ TypeNode t = this.DeclaringType;
+ if (t == null) t = this as TypeNode;
+ Module m = t == null ? null : t.DeclaringModule;
+ TrivialHashtable cache = m == null ? null : m.GetMemberDocumentationCache();
+ if (cache == null) return null;
+ return this.documentation = (XmlNode)cache[this.DocumentationId.UniqueIdKey];
+ }
+ set
+ {
+ this.documentation = value;
+ }
+ }
+ protected Identifier documentationId;
+ protected virtual Identifier GetDocumentationId()
+ {
+ return Identifier.Empty;
+ }
+ /// <summary>
+ /// The value of the name attribute of the XML element whose body is the XML fragment returned by Documentation.
+ /// </summary>
+ public Identifier DocumentationId
+ {
+ get
+ {
+ Identifier documentationId = this.documentationId;
+ if (documentationId != null) return documentationId;
+ return this.DocumentationId = this.GetDocumentationId();
+ }
+ set
+ {
+ this.documentationId = value;
+ }
+ }
+ protected string helpText;
+ /// <summary>
+ /// The value of the summary child element of the XML fragment returned by Documentation. All markup is stripped from the value.
+ /// </summary>
+ public virtual string HelpText
+ {
+ get
+ {
+ string helpText = this.helpText;
+ if (helpText != null) return helpText;
+ XmlNode documentation = this.Documentation;
+ if (documentation != null && documentation.HasChildNodes)
+ {
+ //^ assume documentation.ChildNodes != null;
+ foreach (XmlNode child in documentation.ChildNodes)
+ if (child.Name == "summary")
+ return this.helpText = this.GetHelpText(child);
+ }
+ return this.helpText = "";
+ }
+ set
+ {
+ this.helpText = value;
+ }
+ }
+ public virtual string GetParameterHelpText(string parameterName)
+ {
+ XmlNode documentation = this.Documentation;
+ if (documentation == null || documentation.ChildNodes == null) return null;
+ foreach (XmlNode cdoc in documentation.ChildNodes)
+ {
+ if (cdoc == null) continue;
+ if (cdoc.Name != "param") continue;
+ if (cdoc.Attributes == null) continue;
+ foreach (XmlAttribute attr in cdoc.Attributes)
+ {
+ if (attr == null || attr.Name != "name" || attr.Value != parameterName) continue;
+ if (!cdoc.HasChildNodes) continue;
+ return this.GetHelpText(cdoc);
+ }
+ }
+ return null;
+ }
+ private string GetHelpText(XmlNode node)
+ {
+ if (node == null) return "";
+ StringBuilder sb = new StringBuilder();
+ if (node.HasChildNodes)
+ {
+ foreach (XmlNode child in node.ChildNodes)
+ {
+ switch (child.NodeType)
+ {
+ case XmlNodeType.Element:
+ string str = this.GetHelpText(child);
+ if (str == null || str.Length == 0) continue;
+ if (sb.Length > 0 && !Char.IsPunctuation(str[0]))
+ sb.Append(' ');
+ sb.Append(str);
+ break;
+ case XmlNodeType.CDATA:
+ case XmlNodeType.Entity:
+ case XmlNodeType.Text:
+ this.AppendValue(sb, child);
+ break;
+ }
+ }
+ }
+ else if (node.Attributes != null)
+ {
+ foreach (XmlAttribute attr in node.Attributes)
+ {
+ this.AppendValue(sb, attr);
+ }
+ }
+ return sb.ToString();
+ }
+ private int filterPriority;
+ public virtual System.ComponentModel.EditorBrowsableState FilterPriority
+ {
+ get
+ {
+ if (this.filterPriority > 0) return (System.ComponentModel.EditorBrowsableState)(this.filterPriority - 1);
+ int prio = 0;
+ XmlNode documentation = this.Documentation;
+ if (documentation != null && documentation.HasChildNodes)
+ {
+ foreach (XmlNode child in documentation.ChildNodes)
+ if (child.Name == "filterpriority")
+ {
+ PlatformHelpers.TryParseInt32(child.InnerText, out prio);
+ switch (prio)
+ {
+ case 2: this.filterPriority = (int)System.ComponentModel.EditorBrowsableState.Advanced; break;
+ case 3: this.filterPriority = (int)System.ComponentModel.EditorBrowsableState.Never; break;
+ default: this.filterPriority = (int)System.ComponentModel.EditorBrowsableState.Always; break;
+ }
+ this.filterPriority++;
+ return (System.ComponentModel.EditorBrowsableState)(this.filterPriority - 1);
+ }
+ }
+ AttributeList attributes = this.Attributes;
+ for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++)
+ {
+ //^ assert attributes != null;
+ AttributeNode attr = attributes[i];
+ if (attr == null || attr.Type == null) continue;
+ if (attr.Expressions == null || attr.Expressions.Count < 1) continue;
+ if (attr.Type.FullName != "System.ComponentModel.EditorBrowsableAttribute") continue;
+ Literal lit = attr.Expressions[0] as Literal;
+ if (lit == null || !(lit.Value is int)) continue;
+ //^ assert lit.Value != null;
+ prio = (int)lit.Value;
+ return (System.ComponentModel.EditorBrowsableState)((this.filterPriority = prio + 1) - 1);
+ }
+ return (System.ComponentModel.EditorBrowsableState)((this.filterPriority = 1) - 1);
+ }
+ set
+ {
+ this.filterPriority = ((int)value) + 1;
+ }
+ }
+ /// <summary>
+ /// Writes out an element with tag "element", name attribute DocumentationId.ToString() and body Documentation using the provided XmlTextWriter instance.
+ /// </summary>
+ public virtual void WriteDocumentation(XmlTextWriter xwriter)
+ {
+ if (this.documentation == null || xwriter == null) return;
+ xwriter.WriteStartElement("member");
+ if (this.DocumentationId == null) return;
+ xwriter.WriteAttributeString("name", this.DocumentationId.ToString());
+ this.documentation.WriteContentTo(xwriter);
+ xwriter.WriteEndElement();
+ }
+ private readonly static char[]/*!*/ tags = { 'E', 'F', 'M', 'P', 'T' };
+ private void AppendValue(StringBuilder/*!*/ sb, XmlNode/*!*/ node)
+ {
+ string str = node.Value;
+ if (str != null)
+ {
+ str = str.Trim();
+ if (str.Length > 2 && str[1] == ':' && str.LastIndexOfAny(tags, 0, 1) == 0)
+ {
+ char tag = str[0];
+ str = str.Substring(2);
+ if (tag == 'T' && str.IndexOf(TargetPlatform.GenericTypeNamesMangleChar) >= 0)
+ {
+ Module mod = null;
+ if (this.DeclaringType != null)
+ mod = this.DeclaringType.DeclaringModule;
+ else if (this is TypeNode)
+ mod = ((TypeNode)this).DeclaringModule;
+ if (mod != null)
+ {
+ Identifier ns;
+ Identifier tn;
+ int i = str.LastIndexOf('.');
+ if (i < 0 || i >= str.Length)
+ {
+ ns = Identifier.Empty;
+ tn = Identifier.For(str);
+ }
+ else
+ {
+ ns = Identifier.For(str.Substring(0, i));
+ tn = Identifier.For(str.Substring(i + 1));
+ }
+ TypeNode t = mod.GetType(ns, tn, true);
+ if (t != null) str = t.GetFullUnmangledNameWithTypeParameters();
+ }
+ }
+ }
+ if (str == null || str.Length == 0) return;
+ bool lastCharWasSpace = false;
+ if (sb.Length > 0 && !Char.IsPunctuation(str[0]) && !Char.IsWhiteSpace(str[0]))
+ {
+ sb.Append(' ');
+ lastCharWasSpace = true;
+ }
+ foreach (char ch in str)
+ {
+ if (Char.IsWhiteSpace(ch))
+ {
+ if (lastCharWasSpace) continue;
+ lastCharWasSpace = true;
+ sb.Append(' ');
+ }
+ else
+ {
+ lastCharWasSpace = false;
+ sb.Append(ch);
+ }
+ }
+ if (sb.Length > 0 && Char.IsWhiteSpace(sb[sb.Length - 1]))
+ sb.Length -= 1;
+ }
+ }
+#endif
+#if FxCop
+ internal string GetName(MemberFormat options)
+ {
+ StringBuilder name = new StringBuilder();
+ GetName(options, name);
+ return name.ToString();
+ }
+ internal virtual void GetName(MemberFormat options, StringBuilder name)
+ {
+ if (options.Type.TypeName != TypeNameFormat.None && this.DeclaringType != null)
+ {
+ this.DeclaringType.GetName(options, name);
+ name.Append('.');
+ }
+ name.Append(this.Name.Name);
+ }
+#endif
+ }
+#if !MinimalReader
+ public class TypeMemberSnippet : Member
+ {
+ public IParserFactory ParserFactory;
+
+ public TypeMemberSnippet()
+ : base(NodeType.TypeMemberSnippet)
+ {
+ }
+ public TypeMemberSnippet(IParserFactory parserFactory, SourceContext sctx)
+ : base(NodeType.TypeMemberSnippet)
+ {
+ this.ParserFactory = parserFactory;
+ this.SourceContext = sctx;
+ }
+ public override string/*!*/ FullName
+ {
+ get { throw new InvalidOperationException(); }
+ }
+ public override bool IsCompilerControlled
+ {
+ get { throw new InvalidOperationException(); }
+ }
+ public override bool IsAssembly
+ {
+ get { throw new InvalidOperationException(); }
+ }
+ public override bool IsFamily
+ {
+ get { throw new InvalidOperationException(); }
+ }
+ public override bool IsFamilyAndAssembly
+ {
+ get { throw new InvalidOperationException(); }
+ }
+ public override bool IsFamilyOrAssembly
+ {
+ get { throw new InvalidOperationException(); }
+ }
+ public override bool IsPrivate
+ {
+ get { throw new InvalidOperationException(); }
+ }
+ public override bool IsPublic
+ {
+ get { throw new InvalidOperationException(); }
+ }
+ public override bool IsSpecialName
+ {
+ get { throw new InvalidOperationException(); }
+ }
+ public override bool IsStatic
+ {
+ get { throw new InvalidOperationException(); }
+ }
+ public override bool IsVisibleOutsideAssembly
+ {
+ get { throw new InvalidOperationException(); }
+ }
+
+ }
+#endif
+ /// <summary>
+ /// The common base class for all types. This type should not be extended directly.
+ /// Instead extend one of the standard subclasses such as Class, Struct or Interface, since in
+ /// the CLR a type has to be an instance of one the subclasses, and a type which does not extend
+ /// one of these types will have no equivalent in the CLR.
+ /// </summary>
+ public abstract class TypeNode : Member
+ {
+#if ExtendedRuntime
+ /// <summary>The invariants and modelfield contracts associated with this type (for now only classes, interfaces, structs).</summary>
+ public TypeContract Contract;
+#endif
+ private int classSize;
+ /// <summary>Specifies the total size in bytes of instances of types with prescribed layout.</summary>
+ public int ClassSize
+ {
+ get { return this.classSize; }
+ set { this.classSize = value; }
+ }
+ private Module declaringModule;
+ /// <summary>The module or assembly to which the compiled type belongs.</summary>
+ public Module DeclaringModule
+ {
+ get { return this.declaringModule; }
+ set { this.declaringModule = value; }
+ }
+ private TypeFlags flags;
+ public TypeFlags Flags
+ {
+ get { return this.flags; }
+ set { this.flags = value; }
+ }
+ /// <summary>The interfaces implemented by this class or struct, or the extended by this interface.</summary>
+ public virtual InterfaceList Interfaces
+ {
+ get { return this.interfaces == null ? new InterfaceList(0) : this.interfaces; }
+ set { this.interfaces = value; }
+ }
+ protected InterfaceList interfaces;
+#if !MinimalReader
+ public InterfaceList InterfaceExpressions;
+#endif
+ private Identifier @namespace;
+ /// <summary>The namespace to which this type belongs. Null if the type is nested inside another type.</summary>
+ public Identifier Namespace
+ {
+ get { return this.@namespace; }
+ set { this.@namespace = value; }
+ }
+ private int packingSize;
+ /// <summary>Specifies the alignment of fields within types with prescribed layout.</summary>
+ public int PackingSize
+ {
+ get { return this.packingSize; }
+ set { this.packingSize = value; }
+ }
+#if !MinimalReader
+ /// <summary>If this type is the combined result of a number of partial type definitions, this lists the partial definitions.</summary>
+ public TypeNodeList IsDefinedBy;
+#endif
+ /// <summary>
+ /// True if this type is the result of a template instantiation with arguments that are themselves template parameters.
+ /// Used to model template instantiations occurring inside templates.
+ /// </summary>
+ public bool IsNotFullySpecialized;
+ public bool NewTemplateInstanceIsRecursive;
+#if !MinimalReader
+ /// <summary>
+ /// If this type is a partial definition, the value of this is the combined type resulting from all the partial definitions.
+ /// </summary>
+ public TypeNode PartiallyDefines;
+ /// <summary>
+ /// The list of extensions of this type, if it's a non-extension type.
+ /// all extensions implement the IExtendTypeNode interface (in the Sing# code base).
+ /// null = empty list
+ /// </summary>
+ private TypeNodeList extensions = null;
+ /// <summary>
+ /// Whether or not the list of extensions has been examined;
+ /// it's a bug to record a new extension after extensions have been examined.
+ /// </summary>
+ private bool extensionsExamined = false;
+ /// <summary>
+ /// Record another extension of this type.
+ /// </summary>
+ /// <param name="extension"></param>
+ public void RecordExtension(TypeNode extension)
+ {
+ Debug.Assert(!extensionsExamined, "adding an extension after they've already been examined");
+ if (this.extensions == null) this.extensions = new TypeNodeList();
+ this.extensions.Add(extension);
+ }
+ /// <summary>
+ /// The property that should be accessed by clients to get the list of extensions of this type.
+ /// </summary>
+ public TypeNodeList Extensions
+ {
+ get
+ {
+ this.extensionsExamined = true;
+ return this.extensions;
+ }
+ set
+ {
+ Debug.Assert(!extensionsExamined, "setting extensions after they've already been examined");
+ this.extensions = value;
+ }
+ }
+ /// <summary>
+ /// When duplicating a type node, we want to transfer the extensions and the extensionsExamined flag without
+ /// treating this as a "touch" that sets the examined flag. Pretty ugly, though.
+ /// </summary>
+ public TypeNodeList ExtensionsNoTouch
+ {
+ get { return this.extensions; }
+ }
+ /// <summary>
+ /// Copy a (possibly transformed) set of extensions from source to the
+ /// receiver, including whether or not the extensions have been examined.
+ /// </summary>
+ public void DuplicateExtensions(TypeNode source, TypeNodeList newExtensions)
+ {
+ if (source == null) return;
+ this.extensions = newExtensions;
+ this.extensionsExamined = source.extensionsExamined;
+ }
+ /// <summary>
+ /// If the receiver is a type extension, return the extendee, otherwise return the receiver.
+ /// [The identity function, except for dialects (e.g. Extensible Sing#) that allow
+ /// extensions and differing views of types]
+ /// </summary>
+ public virtual TypeNode/*!*/ EffectiveTypeNode
+ {
+ get
+ {
+ return this;
+ }
+ }
+ /// <summary>
+ /// Return whether t1 represents the same type as t2 (or both are null).
+ /// This copes with the cases where t1 and/or t2 may be type views and/or type extensions, as
+ /// in Extensible Sing#.
+ /// </summary>
+ public static bool operator ==(TypeNode t1, TypeNode t2)
+ {
+ return
+ (object)t1 == null ?
+ (object)t2 == null :
+ (object)t2 != null && (object)t1.EffectiveTypeNode == (object)t2.EffectiveTypeNode;
+ }
+ // modify the other operations related to equality
+ public static bool operator !=(TypeNode t1, TypeNode t2)
+ {
+ return !(t1 == t2);
+ }
+ public override bool Equals(Object other)
+ {
+ return this == (other as TypeNode);
+ }
+ public override int GetHashCode()
+ {
+ TypeNode tn = this.EffectiveTypeNode;
+ if ((object)tn == (object)this)
+ {
+ return base.GetHashCode();
+ }
+ else
+ {
+ return tn.GetHashCode();
+ }
+ }
+#endif
+ /// <summary>
+ /// A delegate that is called the first time Members is accessed, if non-null.
+ /// Provides for incremental construction of the type node.
+ /// Must not leave Members null.
+ /// </summary>
+ public TypeMemberProvider ProvideTypeMembers;
+ /// <summary>
+ /// The type of delegates that fill in the Members property of the given type.
+ /// </summary>
+ public delegate void TypeMemberProvider(TypeNode/*!*/ type, object/*!*/ handle);
+ /// <summary>
+ /// A delegate that is called the first time NestedTypes is accessed, if non-null.
+ /// </summary>
+ public NestedTypeProvider ProvideNestedTypes;
+ /// <summary>
+ /// The type of delegates that fill in the NestedTypes property of the given type.
+ /// </summary>
+ public delegate void NestedTypeProvider(TypeNode/*!*/ type, object/*!*/ handle);
+ /// <summary>
+ /// A delegate that is called the first time Attributes is accessed, if non-null.
+ /// Provides for incremental construction of the type node.
+ /// Must not leave Attributes null.
+ /// </summary>
+ public TypeAttributeProvider ProvideTypeAttributes;
+ /// <summary>
+ /// The type of delegates that fill in the Attributes property of the given type.
+ /// </summary>
+ public delegate void TypeAttributeProvider(TypeNode/*!*/ type, object/*!*/ handle);
+ /// <summary>
+ /// Opaque information passed as a parameter to the delegates in ProvideTypeMembers et al.
+ /// Typically used to associate this namespace instance with a helper object.
+ /// </summary>
+ public object ProviderHandle;
+ private TypeNodeList templateInstances;
+ /// <summary>Contains all the types instantiated from this non generic template type.</summary>
+ public TypeNodeList TemplateInstances
+ {
+ get { return this.templateInstances; }
+ set { this.templateInstances = value; }
+ }
+ internal TypeNode(NodeType nodeType)
+ : base(nodeType)
+ {
+#if ExtendedRuntime
+ this.Contract = new TypeContract(this, true);
+#endif
+ }
+ internal TypeNode(NodeType nodeType, NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
+ : base(nodeType)
+ {
+ this.ProvideNestedTypes = provideNestedTypes;
+ this.ProvideTypeAttributes = provideAttributes;
+ this.ProvideTypeMembers = provideMembers;
+ this.ProviderHandle = handle;
+#if !MinimalReader
+ this.isNormalized = true;
+#endif
+#if ExtendedRuntime
+ this.Contract = new TypeContract(this);
+#endif
+ }
+ internal TypeNode(Module declaringModule, TypeNode declaringType, AttributeList attributes, TypeFlags flags,
+ Identifier Namespace, Identifier name, InterfaceList interfaces, MemberList members, NodeType nodeType)
+ : base(null, attributes, name, nodeType)
+ {
+ this.DeclaringModule = declaringModule;
+ this.DeclaringType = declaringType;
+ this.Flags = flags;
+ this.Interfaces = interfaces;
+ this.members = members;
+ this.Namespace = Namespace;
+#if ExtendedRuntime
+ this.Contract = new TypeContract(this, true);
+#endif
+ }
+ public override AttributeList Attributes
+ {
+ get
+ {
+ if (this.attributes == null)
+ {
+ if (this.ProvideTypeAttributes != null && this.ProviderHandle != null)
+ {
+ lock (Module.GlobalLock)
+ {
+ if (this.attributes == null)
+ this.ProvideTypeAttributes(this, this.ProviderHandle);
+ }
+ }
+ else
+ this.attributes = new AttributeList(0);
+ }
+ return this.attributes;
+ }
+ set
+ {
+ this.attributes = value;
+ }
+ }
+ protected SecurityAttributeList securityAttributes;
+ /// <summary>Contains declarative security information associated with the type.</summary>
+ public SecurityAttributeList SecurityAttributes
+ {
+ get
+ {
+ if (this.securityAttributes != null) return this.securityAttributes;
+ if (this.attributes == null)
+ {
+ 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
+ if (al != null) al = null;
+ if (this.securityAttributes != null) return this.securityAttributes;
+ }
+ return this.securityAttributes = new SecurityAttributeList(0);
+ }
+ set
+ {
+ this.securityAttributes = value;
+ }
+ }
+ /// <summary>The type from which this type is derived. Null in the case of interfaces and System.Object.</summary>
+ public virtual TypeNode BaseType
+ {
+ get
+ {
+ switch (this.NodeType)
+ {
+ case NodeType.ArrayType: return CoreSystemTypes.Array;
+ case NodeType.ClassParameter:
+ case NodeType.Class: return ((Class)this).BaseClass;
+ case NodeType.DelegateNode: return CoreSystemTypes.MulticastDelegate;
+ case NodeType.EnumNode: return CoreSystemTypes.Enum;
+ case NodeType.Struct:
+#if !MinimalReader
+ case NodeType.TupleType:
+ case NodeType.TypeAlias:
+ case NodeType.TypeIntersection:
+ case NodeType.TypeUnion:
+#endif
+ return CoreSystemTypes.ValueType;
+ default: return null;
+ }
+ }
+ }
+ protected internal MemberList defaultMembers;
+ /// <summary>A list of any members of this type that have the DefaultMember attribute.</summary>
+ public virtual MemberList DefaultMembers
+ {
+ get
+ {
+ int n = this.Members.Count;
+ if (n != this.memberCount)
+ {
+ this.UpdateMemberTable(n);
+ this.defaultMembers = null;
+ }
+ if (this.defaultMembers == null)
+ {
+ AttributeList attrs = this.Attributes;
+ Identifier defMemName = null;
+ for (int j = 0, m = attrs == null ? 0 : attrs.Count; j < m; j++)
+ {
+ //^ assert attrs != null;
+ AttributeNode attr = attrs[j];
+ if (attr == null) continue;
+ MemberBinding mb = attr.Constructor as MemberBinding;
+ if (mb != null && mb.BoundMember != null && mb.BoundMember.DeclaringType == SystemTypes.DefaultMemberAttribute)
+ {
+ if (attr.Expressions != null && attr.Expressions.Count > 0)
+ {
+ Literal lit = attr.Expressions[0] as Literal;
+ if (lit != null && lit.Value is string)
+ defMemName = Identifier.For((string)lit.Value);
+ }
+ break;
+ }
+ Literal litc = attr.Constructor as Literal;
+ if (litc != null && (litc.Value as TypeNode) == SystemTypes.DefaultMemberAttribute)
+ {
+ if (attr.Expressions != null && attr.Expressions.Count > 0)
+ {
+ Literal lit = attr.Expressions[0] as Literal;
+ if (lit != null && lit.Value is string)
+ defMemName = Identifier.For((string)lit.Value);
+ }
+ break;
+ }
+ }
+ if (defMemName != null)
+ this.defaultMembers = this.GetMembersNamed(defMemName);
+ else
+ this.defaultMembers = new MemberList(0);
+ }
+ return this.defaultMembers;
+ }
+ set
+ {
+ this.defaultMembers = value;
+ }
+ }
+ protected string fullName;
+ public override string/*!*/ FullName
+ {
+ get
+ {
+ if (this.fullName != null) return this.fullName;
+ if (this.DeclaringType != null)
+ return this.fullName = this.DeclaringType.FullName + "+" + (this.Name == null ? "" : this.Name.ToString());
+ else if (this.Namespace != null && this.Namespace.UniqueIdKey != Identifier.Empty.UniqueIdKey)
+ return this.fullName = this.Namespace.ToString() + "." + (this.Name == null ? "" : this.Name.ToString());
+ else if (this.Name != null)
+ return this.fullName = this.Name.ToString();
+ else
+ return this.fullName = "";
+ }
+ }
+#if !MinimalReader
+ // the same as FullName, except for dialects like Sing# with type extensions where names of
+ // type extensions may get mangled; in that case, this reports the name of the effective type node.
+ public virtual string FullNameDuringParsing
+ {
+ get { return this.FullName; }
+ }
+#endif
+ public virtual string GetFullUnmangledNameWithoutTypeParameters()
+ {
+ if (this.DeclaringType != null)
+ return this.DeclaringType.GetFullUnmangledNameWithoutTypeParameters() + "+" + this.GetUnmangledNameWithoutTypeParameters();
+ else if (this.Namespace != null && this.Namespace.UniqueIdKey != Identifier.Empty.UniqueIdKey)
+ return this.Namespace.ToString() + "." + this.GetUnmangledNameWithoutTypeParameters();
+ else
+ return this.GetUnmangledNameWithoutTypeParameters();
+ }
+ public virtual string GetFullUnmangledNameWithTypeParameters()
+ {
+ if (this.DeclaringType != null)
+ return this.DeclaringType.GetFullUnmangledNameWithTypeParameters() + "+" + this.GetUnmangledNameWithTypeParameters(true);
+ else if (this.Namespace != null && this.Namespace.UniqueIdKey != Identifier.Empty.UniqueIdKey)
+ return this.Namespace.ToString() + "." + this.GetUnmangledNameWithTypeParameters(true);
+ else
+ return this.GetUnmangledNameWithTypeParameters(true);
+ }
+ public virtual string GetUnmangledNameWithTypeParameters()
+ {
+ return this.GetUnmangledNameWithTypeParameters(false);
+ }
+ private string GetUnmangledNameWithTypeParameters(bool fullNamesForTypeParameters)
+ {
+ StringBuilder sb = new StringBuilder(this.GetUnmangledNameWithoutTypeParameters());
+ TypeNodeList templateParameters = this.TemplateParameters;
+ if (this.Template != null) templateParameters = this.TemplateArguments;
+ for (int i = 0, n = templateParameters == null ? 0 : templateParameters.Count; i < n; i++)
+ {
+ //^ assert templateParameters != null;
+ TypeNode tpar = templateParameters[i];
+ if (tpar == null) continue;
+ if (i == 0)
+ sb.Append('<');
+ else
+ sb.Append(',');
+ if (tpar.Name != null)
+ if (fullNamesForTypeParameters)
+ sb.Append(tpar.GetFullUnmangledNameWithTypeParameters());
+ else
+ sb.Append(tpar.GetUnmangledNameWithTypeParameters());
+ if (i == n - 1)
+ sb.Append('>');
+ }
+ return sb.ToString();
+ }
+ protected static readonly char[]/*!*/ MangleChars = new char[] { '!', '>' };
+ public virtual string/*!*/ GetUnmangledNameWithoutTypeParameters()
+ {
+ TypeNode.MangleChars[0] = TargetPlatform.GenericTypeNamesMangleChar;
+ if (this.Template != null) return this.Template.GetUnmangledNameWithoutTypeParameters();
+ if (this.Name == null) return "";
+ string name = this.Name.ToString();
+ if (this.TemplateParameters != null && this.TemplateParameters.Count > 0)
+ {
+ int lastMangle = name.LastIndexOfAny(TypeNode.MangleChars);
+ if (lastMangle >= 0)
+ {
+ if (name[lastMangle] == '>') lastMangle++;
+ return name.Substring(0, lastMangle);
+ }
+ }
+ return name;
+ }
+
+#if !MinimalReader
+ public virtual string GetSerializedTypeName()
+ {
+ bool isAssemblyQualified = true;
+ return this.GetSerializedTypeName(this, ref isAssemblyQualified);
+ }
+ string GetSerializedTypeName(TypeNode/*!*/ type, ref bool isAssemblyQualified)
+ {
+ if (type == null) return null;
+ StringBuilder sb = new StringBuilder();
+ TypeModifier tMod = type as TypeModifier;
+ if (tMod != null)
+ type = tMod.ModifiedType;
+ ArrayType arrType = type as ArrayType;
+ if (arrType != null)
+ {
+ type = arrType.ElementType;
+ bool isAssemQual = false;
+ this.AppendSerializedTypeName(sb, arrType.ElementType, ref isAssemQual);
+ if (arrType.IsSzArray())
+ sb.Append("[]");
+ else
+ {
+ sb.Append('[');
+ if (arrType.Rank == 1) sb.Append('*');
+ for (int i = 1; i < arrType.Rank; i++) sb.Append(',');
+ sb.Append(']');
+ }
+ goto done;
+ }
+ Pointer pointer = type as Pointer;
+ if (pointer != null)
+ {
+ type = pointer.ElementType;
+ bool isAssemQual = false;
+ this.AppendSerializedTypeName(sb, pointer.ElementType, ref isAssemQual);
+ sb.Append('*');
+ goto done;
+ }
+ Reference reference = type as Reference;
+ if (reference != null)
+ {
+ type = reference.ElementType;
+ bool isAssemQual = false;
+ this.AppendSerializedTypeName(sb, reference.ElementType, ref isAssemQual);
+ sb.Append('&');
+ goto done;
+ }
+ if (type.Template == null)
+ sb.Append(type.FullName);
+ else
+ {
+ sb.Append(type.Template.FullName);
+ sb.Append('[');
+ for (int i = 0, n = type.TemplateArguments == null ? 0 : type.TemplateArguments.Count; i < n; i++)
+ {
+ //^ assert type.TemplateArguments != null;
+ bool isAssemQual = true;
+ this.AppendSerializedTypeName(sb, type.TemplateArguments[i], ref isAssemQual);
+ if (i < n - 1) sb.Append(',');
+ }
+ sb.Append(']');
+ }
+ done:
+ if (isAssemblyQualified)
+ this.AppendAssemblyQualifierIfNecessary(sb, type, out isAssemblyQualified);
+ return sb.ToString();
+ }
+ void AppendAssemblyQualifierIfNecessary(StringBuilder/*!*/ sb, TypeNode type, out bool isAssemQualified)
+ {
+ isAssemQualified = false;
+ if (type == null) return;
+ AssemblyNode referencedAssembly = type.DeclaringModule as AssemblyNode;
+ if (referencedAssembly != null)
+ {
+ sb.Append(", ");
+ sb.Append(referencedAssembly.StrongName);
+ isAssemQualified = true;
+ }
+ }
+ void AppendSerializedTypeName(StringBuilder/*!*/ sb, TypeNode type, ref bool isAssemQualified)
+ {
+ if (type == null) return;
+ string argTypeName = this.GetSerializedTypeName(type, ref isAssemQualified);
+ if (isAssemQualified) sb.Append('[');
+ sb.Append(argTypeName);
+ if (isAssemQualified) sb.Append(']');
+ }
+#endif
+
+ /// <summary>
+ /// Return the name the constructor should have in this type node. By default, it's
+ /// the same as the name of the enclosing type node, but it can be different in e.g.
+ /// extensions in Extensible Sing#
+ /// </summary>
+ public virtual Identifier ConstructorName
+ {
+ get
+ {
+ if (this.constructorName == null)
+ {
+ Identifier id = this.Name;
+ if (this.IsNormalized && this.IsGeneric)
+ id = Identifier.For(this.GetUnmangledNameWithoutTypeParameters());
+ this.constructorName = id;
+ }
+ return this.constructorName;
+ }
+ }
+ private Identifier constructorName;
+
+
+ /// <summary>True if the type is an abstract class or an interface.</summary>
+ public virtual bool IsAbstract
+ {
+ get
+ {
+ return (this.Flags & TypeFlags.Abstract) != 0;
+ }
+ }
+ public override bool IsAssembly
+ {
+ get
+ {
+ TypeFlags visibility = this.Flags & TypeFlags.VisibilityMask;
+ return visibility == TypeFlags.NotPublic || visibility == TypeFlags.NestedAssembly;
+ }
+ }
+ public override bool IsCompilerControlled
+ {
+ get { return false; }
+ }
+ public override bool IsFamily
+ {
+ get { return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedFamily; }
+ }
+ public override bool IsFamilyAndAssembly
+ {
+ get { return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedFamANDAssem; }
+ }
+ public override bool IsFamilyOrAssembly
+ {
+ get { return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedFamORAssem; }
+ }
+ protected bool isGeneric;
+ /// <summary>True if this type is a template conforming to the rules of a generic type in the CLR.</summary>
+ public virtual bool IsGeneric
+ {
+ get
+ {
+ return this.isGeneric;
+ }
+ set
+ {
+ this.isGeneric = value;
+ }
+ }
+#if ExtendedRuntime
+ public static bool IsImmutable(TypeNode type) {
+ type = TypeNode.StripModifiers(type);
+ if (type == null) return false;
+ if (type.TypeCode != TypeCode.Object) return true;
+ if (type.GetAttribute(SystemTypes.ImmutableAttribute) != null) return true;
+ if (type.IsValueType && type.DeclaringModule == CoreSystemTypes.SystemAssembly) return true; //hack.
+ return false;
+ }
+#endif
+ public virtual bool IsNestedAssembly
+ {
+ get { return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedAssembly; }
+ }
+ public virtual bool IsNestedFamily
+ {
+ get { return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedFamily; }
+ }
+ public virtual bool IsNestedFamilyAndAssembly
+ {
+ get { return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedFamANDAssem; }
+ }
+ public virtual bool IsNestedInternal
+ {
+ get { return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedFamORAssem; }
+ }
+ public virtual bool IsNestedIn(TypeNode type)
+ {
+ for (TypeNode decType = this.DeclaringType; decType != null; decType = decType.DeclaringType)
+ {
+ if (decType == type) return true;
+ }
+ return false;
+ }
+ public virtual bool IsNestedPublic
+ {
+ get { return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedPublic; }
+ }
+ public virtual bool IsNonPublic
+ {
+ get { return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NotPublic; }
+ }
+#if !MinimalReader
+ protected bool isNormalized;
+ /// <summary>
+ /// 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
+ /// from CLR module or assembly. Such a node can be written out as compiled code to an assembly or module without further processing.
+ /// </summary>
+ public virtual bool IsNormalized
+ {
+ get
+ {
+ if (this.isNormalized) return true;
+ if (this.DeclaringModule == null) return false;
+ return this.isNormalized = this.DeclaringModule.IsNormalized;
+ }
+ set
+ {
+ this.isNormalized = value;
+ }
+ }
+#endif
+ public override bool IsPrivate
+ {
+ get { return (this.Flags & TypeFlags.VisibilityMask) == TypeFlags.NestedPrivate; }
+ }
+ /// <summary>True if values of this type can be compared directly in CLR IL instructions.</summary>
+ public virtual bool IsPrimitiveComparable
+ {
+ get
+ {
+ switch (this.typeCode)
+ {
+ case ElementType.Boolean:
+ case ElementType.Char:
+ case ElementType.Int8:
+ case ElementType.Int16:
+ case ElementType.Int32:
+ case ElementType.Int64:
+ case ElementType.IntPtr:
+ case ElementType.UInt8:
+ case ElementType.UInt16:
+ case ElementType.UInt32:
+ case ElementType.UInt64:
+ case ElementType.UIntPtr:
+ case ElementType.Single:
+ case ElementType.Double:
+ return true;
+ default:
+ return !(this is Struct) || this is EnumNode || this is Pointer;
+ }
+ }
+ }
+ /// <summary>True if values of this type are integers that can be processed by CLR IL instructions.</summary>
+ public virtual bool IsPrimitiveInteger
+ {
+ get
+ {
+ switch (this.typeCode)
+ {
+ case ElementType.Int8:
+ case ElementType.Int16:
+ case ElementType.Int32:
+ case ElementType.Int64:
+ case ElementType.IntPtr:
+ case ElementType.UInt8:
+ case ElementType.UInt16:
+ case ElementType.UInt32:
+ case ElementType.UInt64:
+ case ElementType.UIntPtr:
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
+ /// <summary>True if values of this type are integers or floating point numbers that can be processed by CLR IL instructions.</summary>
+ public virtual bool IsPrimitiveNumeric
+ {
+ get
+ {
+ switch (this.typeCode)
+ {
+ case ElementType.Int8:
+ case ElementType.Int16:
+ case ElementType.Int32:
+ case ElementType.Int64:
+ case ElementType.IntPtr:
+ case ElementType.UInt8:
+ case ElementType.UInt16:
+ case ElementType.UInt32:
+ case ElementType.UInt64:
+ case ElementType.UIntPtr:
+ case ElementType.Single:
+ case ElementType.Double:
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
+ /// <summary>True if values of this type are unsigned integers that can be processed by CLR IL instructions.</summary>
+ public virtual bool IsPrimitiveUnsignedInteger
+ {
+ get
+ {
+ switch (this.typeCode)
+ {
+ case ElementType.UInt8:
+ case ElementType.UInt16:
+ case ElementType.UInt32:
+ case ElementType.UInt64:
+ case ElementType.UIntPtr:
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
+ public override bool IsPublic
+ {
+ get
+ {
+ TypeFlags visibility = this.Flags & TypeFlags.VisibilityMask;
+ return visibility == TypeFlags.Public || visibility == TypeFlags.NestedPublic;
+ }
+ }
+ /// <summary>True if values of this type can be processed by CLR IL instructions.</summary>
+ public virtual bool IsPrimitive
+ {
+ get
+ {
+ switch (this.typeCode)
+ {
+ case ElementType.Boolean:
+ case ElementType.Char:
+ case ElementType.Double:
+ case ElementType.Int16:
+ case ElementType.Int32:
+ case ElementType.Int64:
+ case ElementType.Int8:
+ case ElementType.IntPtr:
+ case ElementType.Single:
+ case ElementType.String:
+ case ElementType.UInt16:
+ case ElementType.UInt32:
+ case ElementType.UInt64:
+ case ElementType.UInt8:
+ case ElementType.UIntPtr:
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
+ /// <summary>True if the type cannot be derived from.</summary>
+ public virtual bool IsSealed
+ {
+ get
+ {
+ return (this.Flags & TypeFlags.Sealed) != 0;
+ }
+ }
+ public override bool IsSpecialName
+ {
+ get { return (this.Flags & TypeFlags.SpecialName) != 0; }
+ }
+ public override bool IsStatic
+ {
+ get { return true; }
+ }
+ /// <summary>True if the identity of the type depends on its structure rather than its name.
+ /// Arrays, pointers and generic type instances are examples of such types.</summary>
+ public virtual bool IsStructural
+ {
+ get
+ {
+ return this.Template != null;
+ }
+ }
+ /// <summary>True if the type serves as a parameter to a type template.</summary>
+ public virtual bool IsTemplateParameter
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ /// <summary>True if the type is a value type containing only fields of unmanaged types.</summary>
+ public virtual bool IsUnmanaged
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ /// <summary>A list of the types that contribute to the structure of a structural type.</summary>
+ public virtual TypeNodeList StructuralElementTypes
+ {
+ get
+ {
+ TypeNodeList result = this.TemplateArguments;
+ if (result != null && result.Count > 0) return result;
+ return this.TemplateParameters;
+ }
+ }
+ /// <summary>True if values of this type are unsigned integers that can be processed by CLR IL instructions.</summary>
+ public virtual bool IsUnsignedPrimitiveNumeric
+ {
+ get
+ {
+ switch (this.typeCode)
+ {
+ case ElementType.UInt8:
+ case ElementType.UInt16:
+ case ElementType.UInt32:
+ case ElementType.UInt64:
+ case ElementType.UIntPtr:
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
+ /// <summary>True if instances of this type have no identity other than their value and are copied upon assignment.</summary>
+ public virtual bool IsValueType
+ {
+ get
+ {
+ switch (this.NodeType)
+ {
+ case NodeType.EnumNode:
+#if !MinimalReader
+ case NodeType.ConstrainedType:
+ case NodeType.TupleType:
+ case NodeType.TypeAlias:
+ case NodeType.TypeIntersection:
+ case NodeType.TypeUnion: return true;
+#endif
+ case NodeType.Struct: return true;
+ default: return false;
+ }
+ }
+ }
+#if ExtendedRuntime
+ /// <summary>
+ /// Returns true if the type is definitely a reference type.
+ /// </summary>
+ public virtual bool IsReferenceType {
+ get {
+ switch (this.NodeType) {
+ case NodeType.Class:
+ case NodeType.Interface:
+ case NodeType.Pointer:
+ case NodeType.ArrayType:
+ case NodeType.DelegateNode:
+ return this != SystemTypes.ValueType && this != SystemTypes.Enum;
+ default:
+ return false;
+ }
+ }
+ }
+#endif
+ /// <summary>
+ /// True if underlying type (modulo type modifiers) is a pointer type (Pointer)
+ /// </summary>
+ public virtual bool IsPointerType
+ {
+ get { return false; }
+ }
+ public override bool IsVisibleOutsideAssembly
+ {
+ get
+ {
+ if (this.DeclaringType != null && !this.DeclaringType.IsVisibleOutsideAssembly) return false;
+ switch (this.Flags & TypeFlags.VisibilityMask)
+ {
+ case TypeFlags.Public:
+ case TypeFlags.NestedPublic:
+ return true;
+ case TypeFlags.NestedFamily:
+ case TypeFlags.NestedFamORAssem:
+ return this.DeclaringType != null && !this.DeclaringType.IsSealed;
+ default:
+ return false;
+ }
+ }
+ }
+ // This field stores those members declared syntactically within
+ // this type node. (Under Extended Sing#, additional members can
+ // be logically part of a type node but declared in a separate
+ // syntactic type node.)
+ protected internal MemberList members;
+ protected volatile internal bool membersBeingPopulated;
+ /// <summary>
+ /// The list of members contained inside this type, by default ignoring any extensions of this type.
+ /// (Subclasses in the Extensible Sing# dialect override this to include members of visible extensions.)
+ /// If the value of members is null and the value of ProvideTypeMembers is not null, the
+ /// TypeMemberProvider delegate is called to fill in the value of this property.
+ /// </summary>
+ public virtual MemberList Members
+ {
+ get
+ {
+ if (this.members == null || this.membersBeingPopulated)
+ if (this.ProvideTypeMembers != null && this.ProviderHandle != null)
+ {
+ lock (Module.GlobalLock)
+ {
+ if (this.members == null)
+ {
+ this.membersBeingPopulated = true;
+ this.ProvideTypeMembers(this, this.ProviderHandle);
+ this.membersBeingPopulated = false;
+#if ExtendedRuntime
+ this.ApplyOutOfBandContracts();
+#endif
+ }
+ }
+ }
+ else
+ this.members = new MemberList();
+ return this.members;
+ }
+ set
+ {
+ this.members = value;
+ this.memberCount = 0;
+ this.memberTable = null;
+ this.constructors = null;
+ this.defaultMembers = null;
+#if !MinimalReader
+ this.explicitCoercionFromTable = null;
+ this.explicitCoercionMethods = null;
+ this.explicitCoercionToTable = null;
+ this.implicitCoercionFromTable = null;
+ this.implicitCoercionMethods = null;
+ this.implicitCoercionToTable = null;
+ this.opFalse = null;
+ this.opTrue = null;
+#endif
+ }
+ }
+#if ExtendedRuntime
+ protected internal virtual void ApplyOutOfBandContracts(){
+ if (this.members == null) return;
+ AssemblyNode declaringAssembly = this.DeclaringModule as AssemblyNode;
+ if (declaringAssembly == null || declaringAssembly.ContractAssembly == null) return;
+ TypeNode contractType = declaringAssembly.ContractAssembly.GetType(this.Namespace, this.Name);
+ if (contractType == null) return;
+
+ // Copy the type-level contract attributes over to the shadowed type, namely "this".
+ int contractsNamespaceKey = SystemTypes.NonNullType.Namespace.UniqueIdKey;
+ foreach (AttributeNode attr in contractType.Attributes) {
+ if (attr.Type.Namespace != null && attr.Type.Namespace.UniqueIdKey == contractsNamespaceKey)
+ this.Attributes.Add(attr);
+ }
+
+ if (this.BaseType != null) { MemberList junk = this.BaseType.Members; if (junk != null) junk = null; }
+ Hashtable contractByFullName = new Hashtable();
+ MemberList contractMembers = contractType.Members;
+ for (int i = 0, n = contractMembers == null ? 0 : contractMembers.Count; i < n; i++){
+ //^ assert contractMembers != null;
+ Field f = contractMembers[i] as Field;
+ if (f != null) {
+ contractByFullName[f.FullName] = f;
+ continue;
+ }
+ Method m = contractMembers[i] as Method;
+ if (m == null ) continue;
+ string methName = this.FullStrippedName(m);
+ contractByFullName[methName] = m;
+ }
+ for (int i = 0, n = members.Count; i < n; i++){
+ Field codeField = members[i] as Field;
+ if (codeField != null) {
+ Field contractField = contractByFullName[codeField.FullName] as Field;
+ if (contractField != null && contractField.Type != null && contractField.Type != codeField.Type) {
+ OptionalModifier optFieldType = contractField.Type as OptionalModifier;
+ if (optFieldType != null && codeField.Type != null) {
+ codeField.Type = OptionalModifier.For(optFieldType.Modifier, codeField.Type);
+ codeField.HasOutOfBandContract = true;
+ }
+ }
+ continue;
+ }
+ Method codeMethod = members[i] as Method;
+ if (codeMethod == null) continue;
+ // we include the return type since some conversion operators result
+ // in overloaded methods whose signatures differ only in return type
+ string methName = this.FullStrippedName(codeMethod);
+ Method contractMethod = contractByFullName[methName] as Method;
+ if (contractMethod != null) {
+ this.CopyContractToMethod(contractMethod, codeMethod);
+ if (codeMethod.OverridesBaseClassMember) {
+ Method overridden = this.FindNearestOverriddenMethod(contractMethod);
+ if (overridden != null)
+ this.CopyContractToMethod(overridden, codeMethod);
+ }
+ } else {
+ // Maybe there isn't a shadow method declared in contractType, but
+ // there still might be out-of-band contracts on an interface method
+ // that the codeMethod implements.
+ if (codeMethod.ImplementedInterfaceMethods != null && codeMethod.ImplementedInterfaceMethods.Count > 0) {
+ foreach (Method m in codeMethod.ImplementedInterfaceMethods) {
+ this.CopyContractToMethod(m, codeMethod);
+ }
+ } else if (codeMethod.ImplicitlyImplementedInterfaceMethods != null) {
+ foreach (Method m in codeMethod.ImplicitlyImplementedInterfaceMethods) {
+ this.CopyContractToMethod(m, codeMethod);
+ }
+ }
+ }
+ }
+ }
+ protected virtual string/*!*/ FullStrippedName(Method/*!*/ m) {
+ StringBuilder sb = new StringBuilder();
+ sb.Append(m.DeclaringType.GetFullUnmangledNameWithTypeParameters());
+ sb.Append('.');
+ if (m.NodeType == NodeType.InstanceInitializer)
+ sb.Append("#ctor");
+ else if (m.Name != null)
+ sb.Append(m.Name.ToString());
+ ParameterList parameters = m.Parameters;
+ for (int i = 0, n = parameters == null ? 0 : parameters.Count; i < n; i++){
+ Parameter par = parameters[i];
+ if (par == null || par.Type == null) continue;
+ TypeNode parType = TypeNode.DeepStripModifiers(par.Type);
+ Reference rt = parType as Reference;
+ if (rt != null && rt.ElementType != null)
+ parType = TypeNode.DeepStripModifiers(rt.ElementType).GetReferenceType();
+ //^ assert parType != null;
+ if (i == 0)
+ sb.Append('(');
+ else
+ sb.Append(',');
+ sb.Append(parType.GetFullUnmangledNameWithTypeParameters());
+ if (i == n-1)
+ sb.Append(')');
+ }
+ if (m.ReturnType != null){
+ TypeNode retType = TypeNode.DeepStripModifiers(m.ReturnType);
+ //^ assert retType != null;
+ sb.Append(retType.GetFullUnmangledNameWithTypeParameters());
+ }
+ return sb.ToString();
+ }
+ protected virtual void CopyContractToMethod(Method/*!*/ contractMethod, Method/*!*/ codeMethod) {
+ codeMethod.HasOutOfBandContract = true;
+ if (codeMethod.Contract == null)
+ codeMethod.Contract = new MethodContract(codeMethod);
+ // setting them to null forces deserialization upon next access to the property
+ // NB: This means that out-of-band contracts can be applied *only* to code that
+ // does *not* have any contracts since this will wipe them out!!
+ codeMethod.Contract.Ensures = null;
+ codeMethod.Contract.Modifies = null;
+ codeMethod.Contract.Requires = null;
+
+ int contractsNamespaceKey = SystemTypes.NonNullType.Namespace.UniqueIdKey;
+ // Copy the method-level contract attributes over to the shadowed method.
+ for (int a = 0; a < contractMethod.Attributes.Count; a++){
+ AttributeNode attr = contractMethod.Attributes[a];
+ if (attr.Type.Namespace != null && attr.Type.Namespace.UniqueIdKey == contractsNamespaceKey)
+ codeMethod.Attributes.Add(attr);
+ }
+
+ // Copy the parameter-level contract attributes and type over to the shadowed method's parameters.
+ ParameterList contractParameters = contractMethod.Parameters;
+ ParameterList codeParameters = codeMethod.Parameters;
+ if (contractParameters != null && codeParameters != null && contractParameters.Count <= codeParameters.Count) {
+ for (int i = 0, n = contractParameters.Count; i < n; i++) {
+ Parameter contractParameter = contractParameters[i];
+ Parameter codeParameter = codeParameters[i];
+ if (contractParameter == null || codeParameter == null) continue;
+ for (int a = 0, m = contractParameter.Attributes == null ? 0 : contractParameter.Attributes.Count; a < m; a++){
+ //^ assert contractParameter.Attributes != null;
+ AttributeNode attr = contractParameter.Attributes[a];
+ if (attr == null || attr.Type == null) continue;
+ if (attr.Type.Namespace != null && attr.Type.Namespace.UniqueIdKey == contractsNamespaceKey){
+ if (codeParameter.Attributes == null) codeParameter.Attributes = new AttributeList();
+ codeParameter.Attributes.Add(attr);
+ }
+ }
+ if (contractParameter.Type != codeParameter.Type)
+ codeParameter.Type = this.CopyModifier(contractParameter.Type, codeParameter.Type);
+ }
+ }
+ if (contractMethod.ReturnType != codeMethod.ReturnType)
+ codeMethod.ReturnType = this.CopyModifier(contractMethod.ReturnType, codeMethod.ReturnType);
+ codeMethod.fullName = null;
+ }
+ private TypeNode CopyModifier(TypeNode contractType, TypeNode codeType) {
+ if (contractType == null) return codeType;
+ Reference rcType = contractType as Reference;
+ if (rcType != null) {
+ contractType = rcType.ElementType;
+ if (contractType == null) return codeType;
+ Reference rcodeType = codeType as Reference;
+ if (rcodeType == null || rcodeType.ElementType == null) return codeType;
+ TypeNode t = CopyModifier(contractType, rcodeType.ElementType);
+ return t.GetReferenceType();
+ }
+ ArrayType acType = contractType as ArrayType;
+ if (acType != null) {
+ contractType = acType.ElementType;
+ if (contractType == null) return codeType;
+ ArrayType acodeType = codeType as ArrayType;
+ if (acodeType == null || acodeType.ElementType == null) return codeType;
+ TypeNode t = CopyModifier(contractType, acodeType.ElementType);
+ return t.GetArrayType(1);
+ }
+ OptionalModifier optModType = contractType as OptionalModifier;
+ if (optModType != null && optModType.Modifier != null) {
+ TypeNode t = CopyModifier(optModType.ModifiedType, codeType);
+ codeType = OptionalModifier.For(optModType.Modifier, t);
+ }
+ if (contractType.Template != null && codeType.Template != null && contractType.TemplateArguments != null && codeType.TemplateArguments != null) {
+ TypeNodeList args = contractType.TemplateArguments.Clone();
+ TypeNodeList codeArgs = codeType.TemplateArguments;
+ for (int i = 0, n = args.Count, m = codeArgs.Count; i < n && i < m; i++) {
+ TypeNode argType = args[i];
+ TypeNode codeArgType = codeArgs[i];
+ if (argType != codeArgType)
+ args[i] = this.CopyModifier(argType, codeArgType);
+ }
+ return codeType.Template.GetTemplateInstance(codeType, args);
+ }
+ return codeType;
+ }
+ public virtual Method FindNearestOverriddenMethod (Method method){
+ if (method == null) return null;
+ int numParams = method.Parameters == null ? 0 : method.Parameters.Count;
+ TypeNode[] paramTypes = new TypeNode[numParams];
+ for (int i=0; i<numParams; i++) paramTypes[i] = method.Parameters[i].Type;
+ for (TypeNode scan = method.DeclaringType.BaseType; scan != null; scan = scan.BaseType){
+ Method overridden = scan.GetMethod(method.Name, paramTypes);
+ if (overridden != null) return overridden;
+ }
+ return null;
+ }
+#endif
+ protected TypeNode template;
+ /// <summary>The (generic) type template from which this type was instantiated. Null if this is not a (generic) type template instance.</summary>
+ public virtual TypeNode Template
+ {
+ get
+ {
+ TypeNode result = this.template;
+ if (result == null)
+ {
+ if (this.isGeneric || TargetPlatform.GenericTypeNamesMangleChar != '_') return null;
+ AttributeList attributes = this.Attributes;
+ lock (this)
+ {
+ if (this.template != null)
+ {
+ if (this.template == TypeNode.NotSpecified)
+ return null;
+ return this.template;
+ }
+#if ExtendedRuntime
+ for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++) {
+ AttributeNode attr = attributes[i];
+ if (attr == null) continue;
+ MemberBinding mb = attr.Constructor as MemberBinding;
+ if (mb == null || mb.BoundMember == null || mb.BoundMember.DeclaringType != SystemTypes.TemplateInstanceAttribute) continue;
+ ExpressionList exprs = attr.Expressions;
+ if (exprs == null || exprs.Count != 2) continue;
+ Literal lit = exprs[0] as Literal;
+ if (lit == null) continue;
+ TypeNode templ = lit.Value as TypeNode;
+ if (templ != null) {
+ lit = exprs[1] as Literal;
+ if (lit == null) continue;
+ object[] types = lit.Value as object[];
+ if (types == null) continue;
+ int m = types == null ? 0 : types.Length;
+ TypeNodeList templateArguments = new TypeNodeList(m);
+ for (int j = 0; j < m; j++) {
+ TypeNode t = types[j] as TypeNode;
+ if (t == null) continue;
+ templateArguments.Add(t);
+ }
+ this.TemplateArguments = templateArguments;
+ return this.template = templ;
+ }
+ }
+#endif
+ if (result == null)
+ this.template = TypeNode.NotSpecified;
+ }
+ }
+ else if (result == TypeNode.NotSpecified)
+ return null;
+ return result;
+ }
+ set
+ {
+ this.template = value;
+ }
+ }
+#if !MinimalReader
+ public TypeNode TemplateExpression;
+#endif
+ protected TypeNodeList templateArguments;
+ /// <summary>The arguments used when this (generic) type template instance was instantiated.</summary>
+ public virtual TypeNodeList TemplateArguments
+ {
+ get
+ {
+ if (this.template == null)
+ {
+ TypeNode templ = this.Template; //Will fill in the arguments
+ if (templ != null) templ = null;
+ }
+ return this.templateArguments;
+ }
+ set
+ {
+ this.templateArguments = value;
+ }
+ }
+#if !MinimalReader
+ public TypeNodeList TemplateArgumentExpressions;
+#endif
+ internal TypeNodeList consolidatedTemplateArguments;
+ public virtual TypeNodeList ConsolidatedTemplateArguments
+ {
+ get
+ {
+ if (this.consolidatedTemplateArguments == null)
+ this.consolidatedTemplateArguments = this.GetConsolidatedTemplateArguments();
+ return this.consolidatedTemplateArguments;
+ }
+ set
+ {
+ this.consolidatedTemplateArguments = value;
+ }
+ }
+ private void AddTemplateParametersFromAttributeEncoding(TypeNodeList result)
+ {
+#if ExtendedRuntime
+ if (result.Count == 0) {
+ AttributeList attributes = this.Attributes;
+ for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++) {
+ AttributeNode attr = attributes[i];
+ if (attr == null) continue;
+ MemberBinding mb = attr.Constructor as MemberBinding;
+ if (mb == null || mb.BoundMember == null || mb.BoundMember.DeclaringType != SystemTypes.TemplateAttribute) continue;
+ ExpressionList exprs = attr.Expressions;
+ if (exprs == null || exprs.Count != 1) continue;
+ Literal lit = exprs[0] as Literal;
+ if (lit == null) continue;
+ object[] types = lit.Value as object[];
+ if (types == null) continue;
+ for (int j = 0, m = types == null ? 0 : types.Length; j < m; j++) {
+ TypeNode t = types[j] as TypeNode;
+ if (t == null) continue;
+ if (t.NodeType == NodeType.TypeParameter || t.NodeType == NodeType.ClassParameter)
+ result.Add(t);
+ }
+ attributes[i] = null;
+ }
+ }
+#endif
+ }
+ internal TypeNodeList templateParameters;
+ /// <summary>The type parameters of this type. Null if this type is not a (generic) type template.</summary>
+ public virtual TypeNodeList TemplateParameters
+ {
+ get
+ {
+ TypeNodeList result = this.templateParameters;
+ if (result == null)
+ {
+ if (this.isGeneric || TargetPlatform.GenericTypeNamesMangleChar != '_') return null; //Can happen when this is nested in a generic type
+ TypeNodeList nestedTypes = this.NestedTypes;
+ lock (this)
+ {
+ if ((result = this.templateParameters) != null) return result.Count == 0 ? null : result;
+ result = new TypeNodeList();
+ for (int i = 0, n = nestedTypes == null ? 0 : nestedTypes.Count; i < n; i++)
+ {
+ TypeNode nt = nestedTypes[i];
+ if (nt == null) continue;
+ if (nt is MethodTypeParameter) continue;
+ if (nt.NodeType == NodeType.TypeParameter || nt.NodeType == NodeType.ClassParameter)
+ result.Add(nt);
+ }
+ this.AddTemplateParametersFromAttributeEncoding(result);
+ this.TemplateParameters = result;
+ }
+ }
+ if (result.Count == 0) return null;
+ return result;
+ }
+ set
+ {
+ if (value == null)
+ {
+ if (this.templateParameters == null) return;
+ if (this.templateParameters.Count > 0)
+ value = new TypeNodeList(0);
+ }
+ this.templateParameters = value;
+ }
+ }
+ protected internal TypeNodeList consolidatedTemplateParameters;
+ public virtual TypeNodeList ConsolidatedTemplateParameters
+ {
+ get
+ {
+ if (this.consolidatedTemplateParameters == null)
+ this.consolidatedTemplateParameters = this.GetConsolidatedTemplateParameters();
+ return this.consolidatedTemplateParameters;
+ }
+ set
+ {
+ this.consolidatedTemplateParameters = value;
+ }
+ }
+ internal ElementType typeCode = ElementType.Class;
+ /// <summary>The System.TypeCode value that Convert.GetTypeCode will return pass an instance of this type as parameter.</summary>
+ public virtual System.TypeCode TypeCode
+ {
+ get
+ {
+ switch (this.typeCode)
+ {
+ case ElementType.Boolean: return System.TypeCode.Boolean;
+ case ElementType.Char: return System.TypeCode.Char;
+ case ElementType.Double: return System.TypeCode.Double;
+ case ElementType.Int16: return System.TypeCode.Int16;
+ case ElementType.Int32: return System.TypeCode.Int32;
+ case ElementType.Int64: return System.TypeCode.Int64;
+ case ElementType.Int8: return System.TypeCode.SByte;
+ case ElementType.Single: return System.TypeCode.Single;
+ case ElementType.UInt16: return System.TypeCode.UInt16;
+ case ElementType.UInt32: return System.TypeCode.UInt32;
+ case ElementType.UInt64: return System.TypeCode.UInt64;
+ case ElementType.UInt8: return System.TypeCode.Byte;
+ case ElementType.Void: return System.TypeCode.Empty;
+ default:
+ if (this == CoreSystemTypes.String) return System.TypeCode.String;
+#if !MinimalReader
+ if (this == CoreSystemTypes.Decimal) return System.TypeCode.Decimal;
+ if (this == CoreSystemTypes.DateTime) return System.TypeCode.DateTime;
+ if (this == CoreSystemTypes.DBNull) return System.TypeCode.DBNull;
+#endif
+ return System.TypeCode.Object;
+ }
+ }
+ }
+ private readonly static TypeNode NotSpecified = new Class();
+#if !FxCop
+ protected
+#endif
+ internal TrivialHashtableUsingWeakReferences structurallyEquivalentMethod;
+#if !MinimalReader
+ /// <summary>
+ /// Returns the methods of an abstract type that have been left unimplemented. Includes methods inherited from
+ /// base classes and interfaces, and methods from any (known) extensions.
+ /// </summary>
+ /// <param name="result">A method list to which the abstract methods must be appended.</param>
+ public virtual void GetAbstractMethods(MethodList/*!*/ result)
+ {
+ if (!this.IsAbstract) return;
+ //For each interface, get abstract methods and keep those that are not implemented by this class or a base class
+ InterfaceList interfaces = this.Interfaces;
+ for (int i = 0, n = interfaces == null ? 0 : interfaces.Count; i < n; i++)
+ {
+ Interface iface = interfaces[i];
+ if (iface == null) continue;
+ MemberList imembers = iface.Members;
+ for (int j = 0, m = imembers == null ? 0 : imembers.Count; j < m; j++)
+ {
+ Method meth = imembers[j] as Method;
+ if (meth == null) continue;
+ if (this.ImplementsExplicitly(meth)) continue;
+ if (this.ImplementsMethod(meth, true)) continue;
+ result.Add(meth);
+ }
+ }
+ }
+#endif
+ protected internal TrivialHashtable szArrayTypes;
+ /// <summary>
+ /// Returns a type representing an array whose elements are of this type. Will always return the same instance for the same rank.
+ /// </summary>
+ /// <param name="rank">The number of dimensions of the array.</param>
+ public virtual ArrayType/*!*/ GetArrayType(int rank)
+ {
+ return this.GetArrayType(rank, false);
+ }
+ public virtual ArrayType/*!*/ GetArrayType(int rank, bool lowerBoundIsUnknown)
+ {
+ if (rank > 1 || lowerBoundIsUnknown) return this.GetArrayType(rank, 0, 0, new int[0], new int[0]);
+ if (this.szArrayTypes == null) this.szArrayTypes = new TrivialHashtable();
+ ArrayType result = (ArrayType)this.szArrayTypes[rank];
+ if (result != null) return result;
+ lock (this)
+ {
+ result = (ArrayType)this.szArrayTypes[rank];
+ if (result != null) return result;
+ this.szArrayTypes[rank] = result = new ArrayType(this, 1);
+ result.Flags &= ~TypeFlags.VisibilityMask;
+ result.Flags |= this.Flags & TypeFlags.VisibilityMask;
+ return result;
+ }
+ }
+ protected internal TrivialHashtable arrayTypes;
+ /// <summary>
+ /// 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.
+ /// </summary>
+ /// <param name="rank">The number of dimensions of the array.</param>
+ /// <param name="sizes">The size of each dimension.</param>
+ /// <param name="loBounds">The lower bound for indices. Defaults to zero.</param>
+ public virtual ArrayType/*!*/ GetArrayType(int rank, int[] sizes, int[] loBounds)
+ {
+ 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);
+ }
+ internal ArrayType/*!*/ GetArrayType(int rank, int numSizes, int numLoBounds, int[]/*!*/ sizes, int[]/*!*/ loBounds)
+ {
+ if (this.arrayTypes == null) this.arrayTypes = new TrivialHashtable();
+ StringBuilder sb = new StringBuilder(rank * 5);
+ for (int i = 0; i < rank; i++)
+ {
+ if (i < numLoBounds) sb.Append(loBounds[i]); else sb.Append('0');
+ if (i < numSizes) { sb.Append(':'); sb.Append(sizes[i]); }
+ sb.Append(',');
+ }
+ Identifier id = Identifier.For(sb.ToString());
+ ArrayType result = (ArrayType)this.arrayTypes[id.UniqueIdKey];
+ if (result != null) return result;
+ lock (this)
+ {
+ result = (ArrayType)this.arrayTypes[id.UniqueIdKey];
+ if (result != null) return result;
+ if (loBounds == null) loBounds = new int[0];
+ this.arrayTypes[id.UniqueIdKey] = result = new ArrayType(this, rank, sizes, loBounds);
+ result.Flags &= ~TypeFlags.VisibilityMask;
+ result.Flags |= this.Flags & TypeFlags.VisibilityMask;
+ return result;
+ }
+ }
+ protected internal MemberList constructors;
+ public virtual MemberList GetConstructors()
+ {
+ if (this.Members.Count != this.memberCount) this.constructors = null;
+ if (this.constructors != null) return this.constructors;
+ lock (this)
+ {
+ if (this.constructors != null) return this.constructors;
+ return this.constructors = TypeNode.WeedOutNonSpecialMethods(this.GetMembersNamed(StandardIds.Ctor), MethodFlags.RTSpecialName);
+ }
+ }
+ /// <summary>
+ /// Returns the constructor with the specified parameter types. Returns null if this type has no such constructor.
+ /// </summary>
+ public virtual InstanceInitializer GetConstructor(params TypeNode[] types)
+ {
+ return (InstanceInitializer)GetMethod(this.GetConstructors(), types);
+ }
+#if !NoXml
+ protected override Identifier GetDocumentationId()
+ {
+ if (this.DeclaringType == null)
+ return Identifier.For("T:" + this.FullName);
+ else
+ return Identifier.For(this.DeclaringType.DocumentationId + "." + this.Name);
+ }
+ internal virtual void AppendDocumentIdMangledName(StringBuilder/*!*/ sb, TypeNodeList methodTypeParameters, TypeNodeList typeParameters)
+ {
+ if (this.DeclaringType != null)
+ {
+ this.DeclaringType.AppendDocumentIdMangledName(sb, methodTypeParameters, typeParameters);
+ sb.Append('.');
+ sb.Append(this.GetUnmangledNameWithoutTypeParameters());
+ }
+ else
+ sb.Append(this.GetFullUnmangledNameWithoutTypeParameters());
+ TypeNodeList templateArguments = this.TemplateArguments;
+ int n = templateArguments == null ? 0 : templateArguments.Count;
+ if (n == 0) return;
+ sb.Append('{');
+ for (int i = 0; i < n; i++)
+ {
+ //^ assert templateArguments != null;
+ TypeNode templArg = templateArguments[i];
+ if (templArg == null) continue;
+ templArg.AppendDocumentIdMangledName(sb, methodTypeParameters, typeParameters);
+ if (i < n - 1) sb.Append(',');
+ }
+ sb.Append('}');
+ }
+#endif
+ internal TrivialHashtable modifierTable;
+ internal TypeNode/*!*/ GetModified(TypeNode/*!*/ modifierType, bool optionalModifier)
+ {
+ if (this.modifierTable == null) this.modifierTable = new TrivialHashtable();
+ TypeNode result = (TypeNode)this.modifierTable[modifierType.UniqueKey];
+ if (result != null) return result;
+ result = optionalModifier ? (TypeNode)new OptionalModifier(modifierType, this) : (TypeNode)new RequiredModifier(modifierType, this);
+ this.modifierTable[modifierType.UniqueKey] = result;
+ return result;
+ }
+ public virtual TypeNode/*!*/ GetGenericTemplateInstance(Module/*!*/ module, TypeNodeList/*!*/ consolidatedArguments)
+ {
+ if (this.DeclaringType == null)
+ return this.GetTemplateInstance(module, null, null, consolidatedArguments);
+ TypeNodeList myArgs = this.GetOwnTemplateArguments(consolidatedArguments);
+ if (myArgs == consolidatedArguments)
+ return this.GetTemplateInstance(module, null, this.DeclaringType, consolidatedArguments);
+ int n = consolidatedArguments.Count;
+ int m = myArgs == null ? 0 : myArgs.Count;
+ int k = n - m;
+ Debug.Assert(k > 0);
+ TypeNodeList parentArgs = new TypeNodeList(k);
+ for (int i = 0; i < k; i++) parentArgs.Add(consolidatedArguments[i]);
+ TypeNode declaringType = this.DeclaringType.GetGenericTemplateInstance(module, parentArgs);
+ TypeNode nestedType = declaringType.GetNestedType(this.Name);
+ if (nestedType == null) { Debug.Fail("template declaring type dummy instance does not have a nested type corresponding to template"); nestedType = this; }
+ if (m == 0) { Debug.Assert(nestedType.template != null); return nestedType; }
+ return nestedType.GetTemplateInstance(module, null, declaringType, myArgs);
+ }
+ public virtual TypeNode/*!*/ GetTemplateInstance(Module module, params TypeNode[] typeArguments)
+ {
+ return this.GetTemplateInstance(module, null, null, new TypeNodeList(typeArguments));
+ }
+ protected virtual void TryToFindExistingInstance(Module/*!*/ module, TypeNode declaringType, TypeNodeList/*!*/ templateArguments, Identifier/*!*/ mangledName,
+ Identifier/*!*/ uniqueMangledName, out TypeNode result, out Identifier unusedMangledName)
+ {
+ unusedMangledName = null;
+ string mangledNameString = mangledName.Name;
+ int n = templateArguments.Count;
+ int tiCount = 0;
+ bool lookInReferencedAssemblies = TargetPlatform.GenericTypeNamesMangleChar != '`'; //REVIEW: huh? why not use IsGeneric?
+ result = module.GetStructurallyEquivalentType(this.Namespace == null ? Identifier.Empty : this.Namespace, mangledName, uniqueMangledName, lookInReferencedAssemblies);
+ if (this.IsGeneric)
+ {
+ if (result == null) unusedMangledName = mangledName;
+ return;
+ }
+ while (result != null)
+ {
+ //Mangled name is the same. But mangling is not unique (types are not qualified with assemblies), so check for equality.
+ if (this == result.Template && (declaringType == result.DeclaringType || !this.IsGeneric))
+ {
+ bool goodMatch = (result.TemplateArguments != null || n == 0) && result.TemplateArguments.Count == n;
+ for (int i = 0; goodMatch && i < n; i++)
+ goodMatch = templateArguments[i] == result.TemplateArguments[i];
+ if (goodMatch) return;
+ }
+ //Mangle some more
+ mangledName = new Identifier(mangledNameString + (++tiCount).ToString());
+ result = module.GetStructurallyEquivalentType(this.Namespace == null ? Identifier.Empty : this.Namespace, mangledName, null, lookInReferencedAssemblies);
+ }
+ if (result == null) unusedMangledName = mangledName;
+ }
+ public virtual Identifier/*!*/ GetMangledTemplateInstanceName(TypeNodeList/*!*/ templateArguments, out Identifier/*!*/ uniqueMangledName, out bool notFullySpecialized)
+ {
+ StringBuilder mangledNameBuilder = new StringBuilder(this.Name.ToString());
+ StringBuilder uniqueMangledNameBuilder = new StringBuilder(this.Name.ToString());
+ uniqueMangledNameBuilder.Append(this.UniqueKey);
+ notFullySpecialized = false;
+ for (int i = 0, n = templateArguments.Count; i < n; i++)
+ {
+ if (i == 0) { mangledNameBuilder.Append('<'); uniqueMangledNameBuilder.Append('<'); }
+ TypeNode t = templateArguments[i];
+ if (t == null || t.Name == null) continue;
+ if (TypeIsNotFullySpecialized(t)) notFullySpecialized = true;
+ mangledNameBuilder.Append(t.FullName);
+ uniqueMangledNameBuilder.Append(t.FullName);
+ uniqueMangledNameBuilder.Append(t.UniqueKey);
+ if (i < n - 1)
+ {
+ mangledNameBuilder.Append(',');
+ uniqueMangledNameBuilder.Append(',');
+ }
+ else
+ {
+ mangledNameBuilder.Append('>');
+ uniqueMangledNameBuilder.Append('>');
+ }
+ }
+ uniqueMangledName = Identifier.For(uniqueMangledNameBuilder.ToString());
+ return Identifier.For(mangledNameBuilder.ToString());
+ }
+ private static bool TypeIsNotFullySpecialized(TypeNode t)
+ {
+ TypeNode tt = TypeNode.StripModifiers(t);
+ //^ assert tt != null;
+ if (tt is TypeParameter || tt is ClassParameter || tt.IsNotFullySpecialized)
+ return true;
+ for (int j = 0, m = tt.StructuralElementTypes == null ? 0 : tt.StructuralElementTypes.Count; j < m; j++)
+ {
+ TypeNode et = tt.StructuralElementTypes[j];
+ if (et == null) continue;
+ if (TypeIsNotFullySpecialized(et)) return true;
+ }
+ return false;
+ }
+ /// <summary>
+ /// Gets an instance for the given template arguments of this (generic) template type.
+ /// </summary>
+ /// <param name="referringType">The type in which the reference to the template instance occurs. If the template is not
+ /// generic, the instance becomes a nested type of the referring type so that it has the same access privileges as the
+ /// code referrring to the instance.</param>
+ /// <param name="templateArguments">The template arguments.</param>
+ /// <returns>An instance of the template. Always the same instance for the same arguments.</returns>
+ public virtual TypeNode/*!*/ GetTemplateInstance(TypeNode referringType, params TypeNode[] templateArguments)
+ {
+ return this.GetTemplateInstance(referringType, new TypeNodeList(templateArguments));
+ }
+ /// <summary>
+ /// Gets an instance for the given template arguments of this (generic) template type.
+ /// </summary>
+ /// <param name="referringType">The type in which the reference to the template instance occurs. If the template is not
+ /// generic, the instance becomes a nested type of the referring type so that it has the same access privileges as the
+ /// code referrring to the instance.</param>
+ /// <param name="templateArguments">The template arguments.</param>
+ /// <returns>An instance of the template. Always the same instance for the same arguments.</returns>
+ public virtual TypeNode/*!*/ GetTemplateInstance(TypeNode referringType, TypeNodeList templateArguments)
+ {
+ if (referringType == null) return this;
+ Module module = referringType.DeclaringModule;
+ return this.GetTemplateInstance(module, referringType, this.DeclaringType, templateArguments);
+ }
+ class CachingModuleForGenericsInstances : Module
+ {
+ public override TypeNode GetStructurallyEquivalentType(Identifier ns, Identifier/*!*/ id, Identifier uniqueMangledName, bool lookInReferencedAssemblies)
+ {
+ if (uniqueMangledName == null) return null;
+ return (TypeNode)this.StructurallyEquivalentType[uniqueMangledName.UniqueIdKey];
+ }
+ }
+ protected static Module/*!*/ cachingModuleForGenericInstances = new CachingModuleForGenericsInstances();
+ public virtual TypeNode/*!*/ GetTemplateInstance(Module module, TypeNode referringType, TypeNode declaringType, TypeNodeList templateArguments)
+ {
+ TypeNodeList templateParameters = this.TemplateParameters;
+ if (module == null || templateArguments == null || (declaringType == null && (templateParameters == null || templateParameters.Count == 0)))
+ return this;
+ if (this.IsGeneric)
+ {
+ referringType = null;
+ module = TypeNode.cachingModuleForGenericInstances;
+ }
+ bool notFullySpecialized;
+ Identifier/*!*/ uniqueMangledName;
+ Identifier mangledName = this.GetMangledTemplateInstanceName(templateArguments, out uniqueMangledName, out notFullySpecialized);
+ TypeNode result;
+ Identifier dummyId;
+ this.TryToFindExistingInstance(module, declaringType, templateArguments, mangledName, uniqueMangledName, out result, out dummyId);
+ if (result != null) return result;
+ if (this.NewTemplateInstanceIsRecursive) return this; //An instance of this template is trying to instantiate the template again
+ lock (Module.GlobalLock)
+ {
+ Identifier unusedMangledName;
+ this.TryToFindExistingInstance(module, declaringType, templateArguments, mangledName, uniqueMangledName, out result, out unusedMangledName);
+ if (result != null) return result;
+ //^ assume unusedMangledName != null;
+ TypeNodeList consolidatedTemplateArguments =
+ declaringType == null ? templateArguments : declaringType.GetConsolidatedTemplateArguments(templateArguments);
+ Duplicator duplicator = new Duplicator(module, referringType);
+ duplicator.RecordOriginalAsTemplate = true;
+ duplicator.SkipBodies = true;
+ duplicator.TypesToBeDuplicated[this.UniqueKey] = this;
+ result = duplicator.VisitTypeNode(this, unusedMangledName, consolidatedTemplateArguments, this.Template == null ? this : this.Template, true);
+ //^ assume result != null;
+ if (module == this.DeclaringModule)
+ {
+ if (this.TemplateInstances == null) this.TemplateInstances = new TypeNodeList();
+ this.TemplateInstances.Add(result);
+ }
+ result.Name = unusedMangledName;
+ result.Name.SourceContext = this.Name.SourceContext;
+ result.fullName = null;
+ if (this.IsGeneric) result.DeclaringModule = this.DeclaringModule;
+ result.DeclaringType = this.IsGeneric || referringType == null ? declaringType : referringType;
+ result.Template = this;
+ result.templateParameters = new TypeNodeList(0);
+ result.consolidatedTemplateParameters = new TypeNodeList(0);
+ result.templateArguments = templateArguments;
+ result.consolidatedTemplateArguments = consolidatedTemplateArguments;
+ result.IsNotFullySpecialized = notFullySpecialized || (declaringType != null && declaringType.IsNotFullySpecialized);
+ module.StructurallyEquivalentType[unusedMangledName.UniqueIdKey] = result;
+ module.StructurallyEquivalentType[uniqueMangledName.UniqueIdKey] = result;
+ Specializer specializer = new Specializer(module, this.ConsolidatedTemplateParameters, consolidatedTemplateArguments);
+ specializer.VisitTypeNode(result);
+ TypeFlags visibility = this.Flags & TypeFlags.VisibilityMask;
+ for (int i = 0, m = templateArguments.Count; i < m; i++)
+ {
+ TypeNode t = templateArguments[i];
+ if (t == null) continue;
+ if (t is TypeParameter || t is ClassParameter || t.IsNotFullySpecialized) continue;
+ visibility = TypeNode.GetVisibilityIntersection(visibility, t.Flags & TypeFlags.VisibilityMask);
+ }
+ result.Flags &= ~TypeFlags.VisibilityMask;
+ result.Flags |= visibility;
+ if (this.IsGeneric) return result;
+#if ExtendedRuntime
+ //Arrange for template instance to be emitted to module and to be recognized as a template instance when imported from module.
+ if (referringType == null){
+ if (visibility == TypeFlags.NestedPublic)
+ visibility = TypeFlags.Public;
+ else if (visibility != TypeFlags.Public)
+ visibility = TypeFlags.NotPublic;
+ module.Types.Add(result);
+ }else{
+ switch (visibility){
+ case TypeFlags.NestedFamANDAssem:
+ case TypeFlags.NestedFamily:
+ case TypeFlags.NestedPrivate:
+ if (result != referringType && this != referringType)
+ referringType.Members.Add(result);
+ else{
+ if (declaringType == null)
+ visibility = TypeFlags.NotPublic;
+ goto default;
+ }
+ break;
+ case TypeFlags.NestedAssembly:
+ if (declaringType == null)
+ visibility = TypeFlags.NotPublic;
+ goto default;
+ case TypeFlags.NestedPublic:
+ if (declaringType == null)
+ visibility = TypeFlags.Public;
+ goto default;
+ default:
+ if (declaringType == null){
+ result.DeclaringType = null;
+ module.Types.Add(result);
+ }else{
+ result.DeclaringType = declaringType;
+ declaringType.Members.Add(result);
+ }
+ break;
+ }
+ }
+ result.Flags &= ~TypeFlags.VisibilityMask;
+ result.Flags |= visibility;
+ AttributeList attrs = result.Attributes;
+ if (attrs == null) attrs = result.Attributes = new AttributeList(1);
+ TypeNode typeArray = CoreSystemTypes.Type.GetArrayType(1);
+ if (TypeNode.templateInstanceAttribute == null) {
+ InstanceInitializer constr = SystemTypes.TemplateInstanceAttribute.GetConstructor(CoreSystemTypes.Type, typeArray);
+ if (constr == null) { Debug.Fail(""); return result; }
+ TypeNode.templateInstanceAttribute = new MemberBinding(null, constr);
+ }
+ int n = templateArguments.Count;
+ TypeNode[] tArgs = new TypeNode[n];
+ for (int i = 0; i < n; i++) tArgs[i] = templateArguments[i];
+ AttributeNode attr = new AttributeNode(TypeNode.templateInstanceAttribute,
+ new ExpressionList(new Literal(this, CoreSystemTypes.Type), new Literal(tArgs, typeArray)));
+ attr.Target = AttributeTargets.Delegate|AttributeTargets.Class|AttributeTargets.Enum|AttributeTargets.Interface|AttributeTargets.Struct;
+ if (attrs.Count > 0 && attrs[0] == null)
+ attrs[0] = attr;
+ else
+ attrs.Add(attr);
+#endif
+ return result;
+ }
+ }
+ protected virtual TypeNodeList GetConsolidatedTemplateArguments()
+ {
+ TypeNodeList typeArgs = this.TemplateArguments;
+ if (this.DeclaringType == null) return typeArgs;
+ TypeNodeList result = this.DeclaringType.ConsolidatedTemplateArguments;
+ if (result == null)
+ {
+ if (this.DeclaringType.IsGeneric && this.DeclaringType.Template == null)
+ result = this.DeclaringType.ConsolidatedTemplateParameters;
+ if (result == null)
+ return typeArgs;
+ }
+ int n = typeArgs == null ? 0 : typeArgs.Count;
+ if (n == 0) return result;
+ result = result.Clone();
+ for (int i = 0; i < n; i++) result.Add(typeArgs[i]);
+ return result;
+ }
+ protected virtual TypeNodeList GetConsolidatedTemplateArguments(TypeNodeList typeArgs)
+ {
+ TypeNodeList result = this.ConsolidatedTemplateArguments;
+ if (result == null || result.Count == 0)
+ {
+ if (this.IsGeneric && this.Template == null)
+ result = this.ConsolidatedTemplateParameters;
+ else
+ return typeArgs;
+ }
+ int n = typeArgs == null ? 0 : typeArgs.Count;
+ if (n == 0) return result;
+ //^ assert typeArgs != null;
+ result = result.Clone();
+ for (int i = 0; i < n; i++) result.Add(typeArgs[i]);
+ return result;
+ }
+ protected virtual TypeNodeList GetConsolidatedTemplateParameters()
+ {
+ TypeNodeList typeParams = this.TemplateParameters;
+ TypeNode declaringType = this.DeclaringType;
+ if (declaringType == null) return typeParams;
+ while (declaringType.Template != null) declaringType = declaringType.Template;
+ TypeNodeList result = declaringType.ConsolidatedTemplateParameters;
+ if (result == null) return typeParams;
+ int n = typeParams == null ? 0 : typeParams.Count;
+ if (n == 0) return result;
+ result = result.Clone();
+ for (int i = 0; i < n; i++) result.Add(typeParams[i]);
+ return result;
+ }
+ protected virtual TypeNodeList GetOwnTemplateArguments(TypeNodeList consolidatedTemplateArguments)
+ {
+ int n = this.TemplateParameters == null ? 0 : this.TemplateParameters.Count;
+ int m = consolidatedTemplateArguments == null ? 0 : consolidatedTemplateArguments.Count;
+ int k = m - n;
+ if (k <= 0) return consolidatedTemplateArguments;
+ TypeNodeList result = new TypeNodeList(n);
+ if (consolidatedTemplateArguments != null)
+ for (int i = 0; i < n; i++)
+ result.Add(consolidatedTemplateArguments[i + k]);
+ return result;
+ }
+#if ExtendedRuntime
+ private static MemberBinding templateInstanceAttribute = null;
+#endif
+ protected internal Pointer pointerType;
+ public virtual Pointer/*!*/ GetPointerType()
+ {
+ Pointer result = this.pointerType;
+ if (result == null)
+ {
+ lock (this)
+ {
+ if (this.pointerType != null) return this.pointerType;
+ result = this.pointerType = new Pointer(this);
+ result.Flags &= ~TypeFlags.VisibilityMask;
+ result.Flags |= this.Flags & TypeFlags.VisibilityMask;
+ result.DeclaringModule = this.DeclaringModule;
+ }
+ }
+ return result;
+ }
+ protected internal Reference referenceType;
+ public virtual Reference/*!*/ GetReferenceType()
+ {
+ Reference result = this.referenceType;
+ if (result == null)
+ {
+ lock (this)
+ {
+ if (this.referenceType != null) return this.referenceType;
+ result = this.referenceType = new Reference(this);
+ result.Flags &= ~TypeFlags.VisibilityMask;
+ result.Flags |= this.Flags & TypeFlags.VisibilityMask;
+ result.DeclaringModule = this.DeclaringModule;
+ }
+ }
+ return result;
+ }
+ //^ [Microsoft.Contracts.SpecPublic]
+ protected internal TrivialHashtable memberTable;
+ protected internal int memberCount;
+ /// <summary>
+ /// Returns a list of all the members declared directly by this type with the specified name.
+ /// Returns an empty list if this type has no such members.
+ /// </summary>
+ public virtual MemberList/*!*/ GetMembersNamed(Identifier name)
+ {
+ if (name == null) return new MemberList(0);
+ MemberList members = this.Members;
+ int n = members == null ? 0 : members.Count;
+ if (n != this.memberCount || this.memberTable == null) this.UpdateMemberTable(n);
+ //^ assert this.memberTable != null;
+ MemberList result = (MemberList)this.memberTable[name.UniqueIdKey];
+ if (result == null)
+ {
+ lock (this)
+ {
+ result = (MemberList)this.memberTable[name.UniqueIdKey];
+ if (result != null) return result;
+ this.memberTable[name.UniqueIdKey] = (result = new MemberList());
+ }
+ }
+ return result;
+ }
+ /// <summary>
+ /// Returns the first event declared by this type with the specified name.
+ /// Returns null if this type has no such event.
+ /// </summary>
+ public virtual Event GetEvent(Identifier name)
+ {
+ MemberList members = this.GetMembersNamed(name);
+ for (int i = 0, n = members.Count; i < n; i++)
+ {
+ Event ev = members[i] as Event;
+ if (ev != null) return ev;
+ }
+ return null;
+ }
+ /// <summary>
+ /// Returns the first field declared by this type with the specified name. Returns null if this type has no such field.
+ /// </summary>
+ public virtual Field GetField(Identifier name)
+ {
+ MemberList members = this.GetMembersNamed(name);
+ for (int i = 0, n = members.Count; i < n; i++)
+ {
+ Field field = members[i] as Field;
+ if (field != null) return field;
+ }
+ return null;
+ }
+ /// <summary>
+ /// Returns the first method declared by this type with the specified name and parameter types. Returns null if this type has no such method.
+ /// </summary>
+ /// <returns></returns>
+ public virtual Method GetMethod(Identifier name, params TypeNode[] types)
+ {
+ return GetMethod(this.GetMembersNamed(name), types);
+ }
+ private static Method GetMethod(MemberList members, params TypeNode[] types)
+ {
+ if (members == null) return null;
+ int m = types == null ? 0 : types.Length;
+ TypeNodeList typeNodes = m == 0 ? null : new TypeNodeList(types);
+ for (int i = 0, n = members.Count; i < n; i++)
+ {
+ Method meth = members[i] as Method;
+ if (meth == null) continue;
+ if (meth.ParameterTypesMatchStructurally(typeNodes)) return meth;
+ }
+ return null;
+ }
+ public Method GetMatchingMethod(Method method)
+ {
+ if (method == null || method.Name == null) return null;
+ MemberList members = this.GetMembersNamed(method.Name);
+ for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++)
+ {
+ Method m = members[i] as Method;
+ if (m == null) continue;
+ if (m.ParametersMatchStructurally(method.Parameters)) return m;
+ }
+ return null;
+ }
+ /// <summary>
+ /// Returns the first nested type declared by this type with the specified name. Returns null if this type has no such nested type.
+ /// </summary>
+ public virtual TypeNode GetNestedType(Identifier name)
+ {
+ if (name == null) return null;
+ if (this.members != null)
+ {
+ MemberList members = this.GetMembersNamed(name);
+ for (int i = 0, n = members.Count; i < n; i++)
+ {
+ TypeNode type = members[i] as TypeNode;
+ if (type != null) return type;
+ }
+ return null;
+ }
+ TypeNodeList nestedTypes = this.NestedTypes;
+ for (int i = 0, n = nestedTypes == null ? 0 : nestedTypes.Count; i < n; i++)
+ {
+ TypeNode type = nestedTypes[i];
+ if (type != null && type.Name.UniqueIdKey == name.UniqueIdKey) return type;
+ }
+ return null;
+ }
+ protected internal TypeNodeList nestedTypes;
+ public virtual TypeNodeList NestedTypes
+ {
+ get
+ {
+ if (this.nestedTypes != null && (this.members == null || this.members.Count == this.memberCount))
+ return this.nestedTypes;
+ if (this.ProvideNestedTypes != null && this.ProviderHandle != null)
+ {
+ lock (Module.GlobalLock)
+ {
+ this.ProvideNestedTypes(this, this.ProviderHandle);
+ }
+ }
+ else
+ {
+ MemberList members = this.Members;
+ TypeNodeList nestedTypes = new TypeNodeList();
+ for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++)
+ {
+ TypeNode nt = members[i] as TypeNode;
+ if (nt == null) continue;
+ nestedTypes.Add(nt);
+ }
+ this.nestedTypes = nestedTypes;
+ }
+ return this.nestedTypes;
+ }
+ set
+ {
+ this.nestedTypes = value;
+ }
+ }
+ /// <summary>
+ /// Returns the first property declared by this type with the specified name and parameter types. Returns null if this type has no such property.
+ /// </summary>
+ public virtual Property GetProperty(Identifier name, params TypeNode[] types)
+ {
+ return GetProperty(this.GetMembersNamed(name), types);
+ }
+ private static Property GetProperty(MemberList members, params TypeNode[] types)
+ {
+ if (members == null) return null;
+ int m = types == null ? 0 : types.Length;
+ TypeNodeList typeNodes = m == 0 ? null : new TypeNodeList(types);
+ for (int i = 0, n = members.Count; i < n; i++)
+ {
+ Property prop = members[i] as Property;
+ if (prop == null) continue;
+ if (prop.ParameterTypesMatch(typeNodes)) return prop;
+ }
+ return null;
+ }
+#if !MinimalReader
+ protected internal MemberList explicitCoercionMethods;
+ public virtual MemberList ExplicitCoercionMethods
+ {
+ get
+ {
+ if (this.Members.Count != this.memberCount) this.explicitCoercionMethods = null;
+ if (this.explicitCoercionMethods != null) return this.explicitCoercionMethods;
+ lock (this)
+ {
+ if (this.explicitCoercionMethods != null) return this.explicitCoercionMethods;
+ return this.explicitCoercionMethods = TypeNode.WeedOutNonSpecialMethods(this.GetMembersNamed(StandardIds.opExplicit), MethodFlags.SpecialName);
+ }
+ }
+ }
+ protected internal MemberList implicitCoercionMethods;
+ public virtual MemberList ImplicitCoercionMethods
+ {
+ get
+ {
+ if (this.Members.Count != this.memberCount) this.implicitCoercionMethods = null;
+ if (this.implicitCoercionMethods != null) return this.implicitCoercionMethods;
+ lock (this)
+ {
+ if (this.implicitCoercionMethods != null) return this.implicitCoercionMethods;
+ return this.implicitCoercionMethods = TypeNode.WeedOutNonSpecialMethods(this.GetMembersNamed(StandardIds.opImplicit), MethodFlags.SpecialName);
+ }
+ }
+ }
+ protected readonly static Method MethodDoesNotExist = new Method();
+ protected internal TrivialHashtable explicitCoercionFromTable;
+ public virtual Method GetExplicitCoercionFromMethod(TypeNode sourceType)
+ {
+ if (sourceType == null) return null;
+ Method result = null;
+ if (this.explicitCoercionFromTable != null)
+ result = (Method)this.explicitCoercionFromTable[sourceType.UniqueKey];
+ if (result == TypeNode.MethodDoesNotExist) return null;
+ if (result != null) return result;
+ lock (this)
+ {
+ if (this.explicitCoercionFromTable != null)
+ result = (Method)this.explicitCoercionFromTable[sourceType.UniqueKey];
+ if (result == TypeNode.MethodDoesNotExist) return null;
+ if (result != null) return result;
+ MemberList coercions = this.ExplicitCoercionMethods;
+ for (int i = 0, n = coercions.Count; i < n; i++)
+ {
+ Method m = (Method)coercions[i];
+ if (sourceType == m.Parameters[0].Type) { result = m; break; }
+ }
+ if (this.explicitCoercionFromTable == null)
+ this.explicitCoercionFromTable = new TrivialHashtable();
+ if (result == null)
+ this.explicitCoercionFromTable[sourceType.UniqueKey] = TypeNode.MethodDoesNotExist;
+ else
+ this.explicitCoercionFromTable[sourceType.UniqueKey] = result;
+ return result;
+ }
+ }
+ protected internal TrivialHashtable explicitCoercionToTable;
+ public virtual Method GetExplicitCoercionToMethod(TypeNode targetType)
+ {
+ if (targetType == null) return null;
+ Method result = null;
+ if (this.explicitCoercionToTable != null)
+ result = (Method)this.explicitCoercionToTable[targetType.UniqueKey];
+ if (result == TypeNode.MethodDoesNotExist) return null;
+ if (result != null) return result;
+ lock (this)
+ {
+ if (this.explicitCoercionToTable != null)
+ result = (Method)this.explicitCoercionToTable[targetType.UniqueKey];
+ if (result == TypeNode.MethodDoesNotExist) return null;
+ if (result != null) return result;
+ MemberList coercions = this.ExplicitCoercionMethods;
+ for (int i = 0, n = coercions.Count; i < n; i++)
+ {
+ Method m = (Method)coercions[i];
+ if (m.ReturnType == targetType) { result = m; break; }
+ }
+ if (this.explicitCoercionToTable == null)
+ this.explicitCoercionToTable = new TrivialHashtable();
+ if (result == null)
+ this.explicitCoercionToTable[targetType.UniqueKey] = TypeNode.MethodDoesNotExist;
+ else
+ this.explicitCoercionToTable[targetType.UniqueKey] = result;
+ }
+ return result;
+ }
+ protected internal TrivialHashtable implicitCoercionFromTable;
+ public virtual Method GetImplicitCoercionFromMethod(TypeNode sourceType)
+ {
+ if (sourceType == null) return null;
+ Method result = null;
+ if (this.implicitCoercionFromTable != null)
+ result = (Method)this.implicitCoercionFromTable[sourceType.UniqueKey];
+ if (result == TypeNode.MethodDoesNotExist) return null;
+ if (result != null) return result;
+ lock (this)
+ {
+ if (this.implicitCoercionFromTable != null)
+ result = (Method)this.implicitCoercionFromTable[sourceType.UniqueKey];
+ if (result == TypeNode.MethodDoesNotExist) return null;
+ if (result != null) return result;
+ MemberList coercions = this.ImplicitCoercionMethods;
+ for (int i = 0, n = coercions.Count; i < n; i++)
+ {
+ Method m = (Method)coercions[i];
+ if (sourceType.IsStructurallyEquivalentTo(TypeNode.StripModifiers(m.Parameters[0].Type))) { result = m; break; }
+ }
+ if (this.implicitCoercionFromTable == null)
+ this.implicitCoercionFromTable = new TrivialHashtable();
+ if (result == null)
+ this.implicitCoercionFromTable[sourceType.UniqueKey] = TypeNode.MethodDoesNotExist;
+ else
+ this.implicitCoercionFromTable[sourceType.UniqueKey] = result;
+ return result;
+ }
+ }
+ protected internal TrivialHashtable implicitCoercionToTable;
+ public virtual Method GetImplicitCoercionToMethod(TypeNode targetType)
+ {
+ if (targetType == null) return null;
+ Method result = null;
+ if (this.implicitCoercionToTable != null)
+ result = (Method)this.implicitCoercionToTable[targetType.UniqueKey];
+ if (result == TypeNode.MethodDoesNotExist) return null;
+ if (result != null) return result;
+ lock (this)
+ {
+ if (this.implicitCoercionToTable != null)
+ result = (Method)this.implicitCoercionToTable[targetType.UniqueKey];
+ if (result == TypeNode.MethodDoesNotExist) return null;
+ if (result != null) return result;
+ MemberList coercions = this.ImplicitCoercionMethods;
+ for (int i = 0, n = coercions.Count; i < n; i++)
+ {
+ Method m = (Method)coercions[i];
+ if (m.ReturnType == targetType) { result = m; break; }
+ }
+ if (this.implicitCoercionToTable == null)
+ this.implicitCoercionToTable = new TrivialHashtable();
+ if (result == null)
+ this.implicitCoercionToTable[targetType.UniqueKey] = TypeNode.MethodDoesNotExist;
+ else
+ this.implicitCoercionToTable[targetType.UniqueKey] = result;
+ return result;
+ }
+ }
+ protected Method opFalse;
+ public virtual Method GetOpFalse()
+ {
+ Method result = this.opFalse;
+ if (result == TypeNode.MethodDoesNotExist) return null;
+ if (result != null) return result;
+ MemberList members = this.Members; //evaluate for side effect
+ if (members != null) members = null;
+ lock (this)
+ {
+ result = this.opFalse;
+ if (result == TypeNode.MethodDoesNotExist) return null;
+ if (result != null) return result;
+ TypeNode t = this;
+ while (t != null)
+ {
+ MemberList opFalses = t.GetMembersNamed(StandardIds.opFalse);
+ if (opFalses != null)
+ for (int i = 0, n = opFalses.Count; i < n; i++)
+ {
+ Method opFalse = opFalses[i] as Method;
+ if (opFalse == null) continue;
+ if (!opFalse.IsSpecialName || !opFalse.IsStatic || !opFalse.IsPublic || opFalse.ReturnType != CoreSystemTypes.Boolean ||
+ opFalse.Parameters == null || opFalse.Parameters.Count != 1) continue;
+ return this.opFalse = opFalse;
+ }
+ t = t.BaseType;
+ }
+ this.opFalse = TypeNode.MethodDoesNotExist;
+ return null;
+ }
+ }
+ protected Method opTrue;
+ public virtual Method GetOpTrue()
+ {
+ Method result = this.opTrue;
+ if (result == TypeNode.MethodDoesNotExist) return null;
+ if (result != null) return result;
+ MemberList members = this.Members; //evaluate for side effect
+ if (members != null) members = null;
+ lock (this)
+ {
+ result = this.opTrue;
+ if (result == TypeNode.MethodDoesNotExist) return null;
+ if (result != null) return result;
+ TypeNode t = this;
+ while (t != null)
+ {
+ MemberList opTrues = t.GetMembersNamed(StandardIds.opTrue);
+ if (opTrues != null)
+ for (int i = 0, n = opTrues.Count; i < n; i++)
+ {
+ Method opTrue = opTrues[i] as Method;
+ if (opTrue == null) continue;
+ if (!opTrue.IsSpecialName || !opTrue.IsStatic || !opTrue.IsPublic || opTrue.ReturnType != CoreSystemTypes.Boolean ||
+ opTrue.Parameters == null || opTrue.Parameters.Count != 1) continue;
+ return this.opTrue = opTrue;
+ }
+ t = t.BaseType;
+ }
+ this.opTrue = TypeNode.MethodDoesNotExist;
+ return null;
+ }
+ }
+#endif
+#if !NoReflection
+ private static Hashtable typeMap; //contains weak references
+ /// <summary>
+ /// Gets a TypeNode instance corresponding to the given System.Type instance.
+ /// </summary>
+ /// <param name="type">A runtime type.</param>
+ /// <returns>A TypeNode instance.</returns>
+ public static TypeNode GetTypeNode(System.Type type)
+ {
+ if (type == null) return null;
+ Hashtable typeMap = TypeNode.typeMap;
+ if (typeMap == null) TypeNode.typeMap = typeMap = Hashtable.Synchronized(new Hashtable());
+ TypeNode result = null;
+ WeakReference wr = (WeakReference)typeMap[type];
+ if (wr != null)
+ {
+ result = wr.Target as TypeNode;
+ if (result == Class.DoesNotExist) return null;
+ if (result != null) return result;
+ }
+#if WHIDBEY
+ if (type.IsGenericType && !type.IsGenericTypeDefinition)
+ {
+ try
+ {
+ TypeNode template = TypeNode.GetTypeNode(type.GetGenericTypeDefinition());
+ if (template == null) return null;
+ TypeNodeList templateArguments = new TypeNodeList();
+ foreach (Type arg in type.GetGenericArguments())
+ templateArguments.Add(TypeNode.GetTypeNode(arg));
+ return template.GetGenericTemplateInstance(template.DeclaringModule, templateArguments);
+ }
+ catch
+ {
+ //TODO: log error
+ return null;
+ }
+ }
+ if (type.IsGenericParameter)
+ {
+ try
+ {
+ int parIndx = type.GenericParameterPosition;
+ System.Reflection.MethodInfo mi = type.DeclaringMethod as System.Reflection.MethodInfo;
+ if (mi != null)
+ {
+ Method m = Method.GetMethod(mi);
+ if (m == null) return null;
+ if (m.TemplateParameters != null && m.TemplateParameters.Count > parIndx)
+ return m.TemplateParameters[parIndx];
+ }
+ else
+ {
+ System.Type ti = type.DeclaringType;
+ TypeNode t = TypeNode.GetTypeNode(ti);
+ if (t == null) return null;
+ if (t.TemplateParameters != null && t.TemplateParameters.Count > parIndx)
+ return t.TemplateParameters[parIndx];
+ }
+ return null;
+ }
+ catch
+ {
+ //TODO: log error
+ return null;
+ }
+ }
+#endif
+ if (type.HasElementType)
+ {
+ TypeNode elemType = TypeNode.GetTypeNode(type.GetElementType());
+ if (elemType == null) return null;
+ if (type.IsArray)
+ result = elemType.GetArrayType(type.GetArrayRank());
+ else if (type.IsByRef)
+ result = elemType.GetReferenceType();
+ else if (type.IsPointer)
+ result = elemType.GetPointerType();
+ else
+ {
+ Debug.Assert(false);
+ result = null;
+ }
+ }
+ else if (type.DeclaringType != null)
+ {
+ TypeNode dType = TypeNode.GetTypeNode(type.DeclaringType);
+ if (dType == null) return null;
+ result = dType.GetNestedType(Identifier.For(type.Name));
+ }
+ else
+ {
+ AssemblyNode assem = AssemblyNode.GetAssembly(type.Assembly);
+ if (assem != null)
+ {
+ result = assem.GetType(Identifier.For(type.Namespace), Identifier.For(type.Name));
+ }
+ }
+ if (result == null)
+ typeMap[type] = new WeakReference(Class.DoesNotExist);
+ else
+ typeMap[type] = new WeakReference(result);
+ return result;
+ }
+ protected internal Type runtimeType;
+ /// <summary>
+ /// Gets a System.Type instance corresponding to this type. The assembly containin this type must be normalized
+ /// and must have a location on disk or must have been loaded via AssemblyNode.GetRuntimeAssembly.
+ /// </summary>
+ /// <returns>A System.Type instance. (A runtime type.)</returns>
+ public virtual Type GetRuntimeType()
+ {
+ if (this.runtimeType == null)
+ {
+ lock (this)
+ {
+ if (this.runtimeType != null) return this.runtimeType;
+#if WHIDBEY
+ if (this.IsGeneric && this.Template != null)
+ {
+ try
+ {
+ TypeNode rootTemplate = this.Template;
+ while (rootTemplate.Template != null)
+ rootTemplate = rootTemplate.Template;
+ Type genType = rootTemplate.GetRuntimeType();
+ if (genType == null) return null;
+ TypeNodeList args = this.ConsolidatedTemplateArguments;
+ Type[] arguments = new Type[args.Count];
+ for (int i = 0; i < args.Count; i++) arguments[i] = args[i].GetRuntimeType();
+ return genType.MakeGenericType(arguments);
+ }
+ catch
+ {
+ //TODO: add error to metadata import errors if type is imported
+ return null;
+ }
+ }
+#endif
+ if (this.DeclaringType != null)
+ {
+ Type dt = this.DeclaringType.GetRuntimeType();
+ if (dt != null)
+ {
+ System.Reflection.BindingFlags flags = System.Reflection.BindingFlags.DeclaredOnly;
+ if (this.IsPublic) flags |= System.Reflection.BindingFlags.Public; else flags |= System.Reflection.BindingFlags.NonPublic;
+ this.runtimeType = dt.GetNestedType(this.Name.ToString(), flags);
+ }
+ }
+ else if (this.DeclaringModule != null && this.DeclaringModule.IsNormalized && this.DeclaringModule.ContainingAssembly != null)
+ {
+ System.Reflection.Assembly runtimeAssembly = this.DeclaringModule.ContainingAssembly.GetRuntimeAssembly();
+ if (runtimeAssembly != null)
+ this.runtimeType = runtimeAssembly.GetType(this.FullName, false);
+ }
+ }
+ }
+ return this.runtimeType;
+ }
+#endif
+ public static TypeFlags GetVisibilityIntersection(TypeFlags vis1, TypeFlags vis2)
+ {
+ switch (vis2)
+ {
+ case TypeFlags.Public:
+ case TypeFlags.NestedPublic:
+ return vis1;
+ case TypeFlags.NotPublic:
+ case TypeFlags.NestedAssembly:
+ switch (vis1)
+ {
+ case TypeFlags.Public:
+ return vis2;
+ case TypeFlags.NestedPublic:
+ case TypeFlags.NestedFamORAssem:
+ return TypeFlags.NestedAssembly;
+ case TypeFlags.NestedFamily:
+ return TypeFlags.NestedFamANDAssem;
+ default:
+ return vis1;
+ }
+ case TypeFlags.NestedFamANDAssem:
+ switch (vis1)
+ {
+ case TypeFlags.Public:
+ case TypeFlags.NestedPublic:
+ case TypeFlags.NestedFamORAssem:
+ case TypeFlags.NestedFamily:
+ return TypeFlags.NestedFamANDAssem;
+ default:
+ return vis1;
+ }
+ case TypeFlags.NestedFamORAssem:
+ switch (vis1)
+ {
+ case TypeFlags.Public:
+ case TypeFlags.NestedPublic:
+ return TypeFlags.NestedFamORAssem;
+ default:
+ return vis1;
+ }
+ case TypeFlags.NestedFamily:
+ switch (vis1)
+ {
+ case TypeFlags.Public:
+ case TypeFlags.NestedPublic:
+ case TypeFlags.NestedFamORAssem:
+ return TypeFlags.NestedFamily;
+ case TypeFlags.NestedAssembly:
+ return TypeFlags.NestedFamANDAssem;
+ default:
+ return vis1;
+ }
+ default:
+ return TypeFlags.NestedPrivate;
+ }
+ }
+ private TrivialHashtable explicitInterfaceImplementations;
+ public bool ImplementsExplicitly(Method method)
+ {
+ if (method == null) return false;
+ TrivialHashtable explicitInterfaceImplementations = this.explicitInterfaceImplementations;
+ if (explicitInterfaceImplementations == null)
+ {
+ MemberList members = this.Members;
+ lock (this)
+ {
+ if ((explicitInterfaceImplementations = this.explicitInterfaceImplementations) == null)
+ {
+ explicitInterfaceImplementations = this.explicitInterfaceImplementations = new TrivialHashtable();
+ for (int i = 0, n = members.Count; i < n; i++)
+ {
+ Method m = members[i] as Method;
+ if (m == null) continue;
+ MethodList implementedInterfaceMethods = m.ImplementedInterfaceMethods;
+ if (implementedInterfaceMethods != null)
+ for (int j = 0, k = implementedInterfaceMethods.Count; j < k; j++)
+ {
+ Method im = implementedInterfaceMethods[j];
+ if (im == null) continue;
+ explicitInterfaceImplementations[im.UniqueKey] = m;
+ }
+ }
+ }
+ }
+ }
+ return explicitInterfaceImplementations[method.UniqueKey] != null;
+ }
+#if !MinimalReader
+ internal bool ImplementsMethod(Method meth, bool checkPublic)
+ {
+ return this.GetImplementingMethod(meth, checkPublic) != null;
+ }
+ public Method GetImplementingMethod(Method meth, bool checkPublic)
+ {
+ if (meth == null) return null;
+ MemberList mems = this.GetMembersNamed(meth.Name);
+ for (int j = 0, m = mems == null ? 0 : mems.Count; j < m; j++)
+ {
+ Method locM = mems[j] as Method;
+ if (locM == null || !locM.IsVirtual || (checkPublic && !locM.IsPublic)) continue;
+ if ((locM.ReturnType != meth.ReturnType && !(locM.ReturnType != null && locM.ReturnType.IsStructurallyEquivalentTo(meth.ReturnType))) ||
+ !locM.ParametersMatchStructurally(meth.Parameters)) continue;
+ return locM;
+ }
+ if (checkPublic && this.BaseType != null)
+ return this.BaseType.GetImplementingMethod(meth, true);
+ return null;
+ }
+#endif
+ /// <summary>
+ /// 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),
+ /// 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,
+ /// or because this type and the target type are zero based single dimensional arrays with assignment compatible reference element types
+ /// </summary>
+ public virtual bool IsAssignableTo(TypeNode targetType)
+ {
+ if (this == CoreSystemTypes.Void) return false;
+ if (targetType == this) return true;
+ if (this == CoreSystemTypes.Object) return false;
+ if (targetType == CoreSystemTypes.Object || this.IsStructurallyEquivalentTo(targetType) ||
+ this.BaseType != null && (this.BaseType.IsAssignableTo(targetType)))
+ return true;
+ if (this.BaseType != null && this.ConsolidatedTemplateParameters != null && this.BaseType.Template != null && this.BaseType.Template.IsAssignableTo(targetType))
+ return true; //When seeing if one template is assignable to another, be sure to strip off template instances along the inheritance chain
+ InterfaceList interfaces = this.Interfaces;
+ if (interfaces == null) return false;
+ for (int i = 0, n = interfaces.Count; i < n; i++)
+ {
+ Interface iface = interfaces[i];
+ if (iface == null) continue;
+ if (iface.IsAssignableTo(targetType)) return true;
+ if (iface.Template != null && this.ConsolidatedTemplateParameters != null && iface.Template.IsAssignableTo(targetType))
+ return true; //When seeing if one template is assignable to another, be sure to strip off template instances along the inheritance chain
+ }
+ return false;
+ }
+ /// <summary>
+ /// Returns true if this type is assignable to some instance of the given template.
+ /// </summary>
+ public virtual bool IsAssignableToInstanceOf(TypeNode targetTemplate)
+ {
+ if (this == CoreSystemTypes.Void || targetTemplate == null) return false;
+ if (targetTemplate.IsStructurallyEquivalentTo(this.Template == null ? this : this.Template) ||
+ this.BaseType != null && (this.BaseType.IsAssignableToInstanceOf(targetTemplate) ||
+ this.BaseType.Template != null && this.BaseType.Template.IsAssignableToInstanceOf(targetTemplate))) return true;
+ InterfaceList interfaces = this.Interfaces;
+ if (interfaces == null) return false;
+ for (int i = 0, n = interfaces.Count; i < n; i++)
+ {
+ Interface iface = interfaces[i];
+ if (iface == null) continue;
+ if (iface.IsAssignableToInstanceOf(targetTemplate)) return true;
+ }
+ return false;
+ }
+ /// <summary>
+ /// Returns true if this type is assignable to some instance of the given template.
+ /// </summary>
+ public virtual bool IsAssignableToInstanceOf(TypeNode targetTemplate, out TypeNodeList templateArguments)
+ {
+ templateArguments = null;
+ if (this == CoreSystemTypes.Void || targetTemplate == null) return false;
+ if (targetTemplate == this.Template)
+ {
+ templateArguments = this.TemplateArguments;
+ return true;
+ }
+ if (this != CoreSystemTypes.Object && this.BaseType != null && this.BaseType.IsAssignableToInstanceOf(targetTemplate, out templateArguments)) return true;
+ InterfaceList interfaces = this.Interfaces;
+ if (interfaces == null) return false;
+ for (int i = 0, n = interfaces.Count; i < n; i++)
+ {
+ Interface iface = interfaces[i];
+ if (iface == null) continue;
+ if (iface.IsAssignableToInstanceOf(targetTemplate, out templateArguments)) return true;
+ }
+ return false;
+ }
+ /// <summary>
+ /// Returns true if otherType is the base class of this type or if the base class of this type is derived from otherType.
+ /// </summary>
+ public virtual bool IsDerivedFrom(TypeNode otherType)
+ {
+ if (otherType == null) return false;
+ TypeNode baseType = this.BaseType;
+ while (baseType != null)
+ {
+ if (baseType == otherType) return true;
+ baseType = baseType.BaseType;
+ }
+ return false;
+ }
+#if !MinimalReader
+ // Not thread safe code...
+ bool isCheckingInheritedFrom = false;
+ public virtual bool IsInheritedFrom(TypeNode otherType)
+ {
+ if (otherType == null) return false;
+ if (this == otherType) return true;
+ bool result = false;
+ if (this.isCheckingInheritedFrom)
+ goto done;
+ this.isCheckingInheritedFrom = true;
+ if (this.Template != null)
+ {
+ result = this.Template.IsInheritedFrom(otherType);
+ goto done;
+ }
+ if (otherType.Template != null)
+ {
+ otherType = otherType.Template;
+ }
+ TypeNode baseType = this.BaseType;
+ if (baseType != null && baseType.IsInheritedFrom(otherType))
+ {
+ result = true;
+ goto done;
+ }
+ InterfaceList interfaces = this.Interfaces;
+ if (interfaces == null) goto done;
+ for (int i = 0, n = interfaces.Count; i < n; i++)
+ {
+ Interface iface = interfaces[i];
+ if (iface == null) continue;
+ if (iface.IsInheritedFrom(otherType))
+ {
+ result = true;
+ goto done;
+ }
+ }
+ done:
+ this.isCheckingInheritedFrom = false;
+ return result;
+ }
+#endif
+ public virtual bool IsStructurallyEquivalentTo(TypeNode type)
+ {
+ if (null == (object)type) return false;
+ if (this == type) return true;
+ if (this.Template == (object)null || type.Template == (object)null)
+ {
+ if (((object)this) == (object)type.Template || ((object)this.Template) == (object)type) return true;
+ Identifier thisName = this.Template == null ? this.Name : this.Template.Name;
+ Identifier typeName = type.Template == null ? type.Name : type.Template.Name;
+ if (thisName == null || typeName == null || thisName.UniqueIdKey != typeName.UniqueIdKey) return false;
+ if (this.NodeType != type.NodeType) return false;
+ if (this.DeclaringType == null || type.DeclaringType == null) return false;
+ }
+ if (this.TemplateArguments == null || type.TemplateArguments == null)
+ {
+ if (this.DeclaringType != null && (this.TemplateArguments == null || this.TemplateArguments.Count == 0) &&
+ (type.TemplateArguments == null || type.TemplateArguments.Count == 0))
+ return this.DeclaringType.IsStructurallyEquivalentTo(type.DeclaringType);
+ return false;
+ }
+ int n = this.TemplateArguments.Count; if (n != type.TemplateArguments.Count) return false;
+ if (this.Template != type.Template && !this.Template.IsStructurallyEquivalentTo(type.Template)) return false;
+ for (int i = 0; i < n; i++)
+ {
+ TypeNode ta1 = this.TemplateArguments[i];
+ TypeNode ta2 = type.TemplateArguments[i];
+ if (null == (object)ta1 || null == (object)ta2) return false;
+ if (ta1 == ta2) continue;
+ if (!ta1.IsStructurallyEquivalentTo(ta2)) return false;
+ }
+ if (this.DeclaringType != null)
+ return this.DeclaringType.IsStructurallyEquivalentTo(type.DeclaringType);
+ return true;
+ }
+ public virtual bool IsStructurallyEquivalentList(TypeNodeList list1, TypeNodeList list2)
+ {
+ if (list1 == null) return list2 == null;
+ if (list2 == null) return false;
+ int n = list1.Count; if (list2.Count != n) return false;
+ for (int i = 0; i < n; i++)
+ {
+ TypeNode t1 = list1[i];
+ TypeNode t2 = list2[i];
+ if (null == (object)t1 || null == (object)t2) return false;
+ if (t1 == t2) continue;
+ if (!t1.IsStructurallyEquivalentTo(t2)) return false;
+ }
+ return true;
+ }
+ public static TypeNode StripModifiers(TypeNode type)
+ //^ ensures t != null ==> result != null;
+ {
+ for (TypeModifier tmod = type as TypeModifier; tmod != null; tmod = type as TypeModifier)
+ type = tmod.ModifiedType;
+ // Don't strip under pointers or refs. We only strip top-level modifiers.
+ return type;
+ }
+#if !MinimalReader
+ public static TypeNode DeepStripModifiers(TypeNode type)
+ //^ ensures type != null ==> result != null;
+ {
+ // strip off any outer type modifiers
+ for (TypeModifier tmod = type as TypeModifier; tmod != null; tmod = type as TypeModifier)
+ type = tmod.ModifiedType;
+ // For arrays and references, strip the inner type and then reconstruct the array or reference
+ ArrayType ar = type as ArrayType;
+ if (ar != null)
+ {
+ TypeNode t = TypeNode.DeepStripModifiers(ar.ElementType);
+ return t.GetArrayType(1);
+ }
+ Reference rt = type as Reference;
+ if (rt != null)
+ {
+ TypeNode t = TypeNode.DeepStripModifiers(rt.ElementType);
+ return t.GetReferenceType();
+ }
+ return type;
+ }
+ /// <summary>
+ /// Strip the given modifier from the type, modulo substructures that are instantiated with respect
+ /// to the given template type. In other words, travers type and templateType in parallel, stripping common
+ /// non-null modifiers, but stop when reaching a type variable in the template type.
+ /// <param name="type">Type to be stripped</param>
+ /// <param name="modifiers">Modifiers to strip off</param>
+ /// <param name="templateType">Template bounding the stripping of type. Passing null for the templateType performs a full DeepStrip</param>
+ /// </summary>
+ public static TypeNode DeepStripModifiers(TypeNode type, TypeNode templateType, params TypeNode[] modifiers)
+ {
+ if (templateType == null) return DeepStripModifiers(type, modifiers);
+ if (templateType is ITypeParameter) return type;
+ // strip off inner modifiers then outer type modifier if it matches
+ OptionalModifier optmod = type as OptionalModifier;
+ if (optmod != null)
+ {
+ OptionalModifier optmodtemplate = (OptionalModifier)templateType; // must be in sync
+ TypeNode t = TypeNode.DeepStripModifiers(optmod.ModifiedType, optmodtemplate.ModifiedType, modifiers);
+ for (int i = 0; i < modifiers.Length; ++i)
+ {
+ if (optmod.Modifier == modifiers[i])
+ {
+ // strip it
+ return t;
+ }
+ }
+ return OptionalModifier.For(optmod.Modifier, t);
+ }
+ RequiredModifier reqmod = type as RequiredModifier;
+ if (reqmod != null)
+ {
+ RequiredModifier reqmodtemplate = (RequiredModifier)templateType; // must be in sync
+ TypeNode t = TypeNode.DeepStripModifiers(reqmod.ModifiedType, reqmodtemplate.ModifiedType, modifiers);
+ for (int i = 0; i < modifiers.Length; ++i)
+ {
+ if (reqmod.Modifier == modifiers[i])
+ {
+ // strip it
+ return t;
+ }
+ }
+ return RequiredModifier.For(reqmod.Modifier, t);
+ }
+ // For arrays and references, strip the inner type and then reconstruct the array or reference
+ ArrayType ar = type as ArrayType;
+ if (ar != null)
+ {
+ ArrayType artemplate = (ArrayType)templateType;
+ TypeNode t = TypeNode.DeepStripModifiers(ar.ElementType, artemplate.ElementType, modifiers);
+ return t.GetArrayType(1);
+ }
+ Reference rt = type as Reference;
+ if (rt != null)
+ {
+ Reference rttemplate = (Reference)templateType;
+ TypeNode t = TypeNode.DeepStripModifiers(rt.ElementType, rttemplate.ElementType, modifiers);
+ return t.GetReferenceType();
+ }
+ // strip template arguments
+ if (type.Template != null && type.TemplateArguments != null && type.TemplateArguments.Count > 0)
+ {
+ TypeNodeList strippedArgs = new TypeNodeList(type.TemplateArguments.Count);
+ for (int i = 0; i < type.TemplateArguments.Count; i++)
+ {
+ //FIX: bug introduced by checkin 16494
+ //templateType may have type parameters in either the TemplateArguments position or the templateParameters position.
+ //This may indicate an inconsistency in the template instantiation representation elsewhere.
+ TypeNodeList templateTypeArgs = templateType.TemplateArguments != null ? templateType.TemplateArguments : templateType.TemplateParameters;
+ strippedArgs.Add(DeepStripModifiers(type.TemplateArguments[i], templateTypeArgs[i], modifiers));
+ }
+ return type.Template.GetTemplateInstance(type, strippedArgs);
+ }
+ return type;
+ }
+
+ public static TypeNode DeepStripModifiers(TypeNode type, params TypeNode[] modifiers)
+ {
+ // strip off inner modifiers then outer type modifier if it matches
+ OptionalModifier optmod = type as OptionalModifier;
+ if (optmod != null)
+ {
+ TypeNode t = TypeNode.DeepStripModifiers(optmod.ModifiedType, modifiers);
+ for (int i = 0; i < modifiers.Length; ++i)
+ {
+ if (optmod.Modifier == modifiers[i])
+ {
+ // strip it
+ return t;
+ }
+ }
+ return OptionalModifier.For(optmod.Modifier, t);
+ }
+ RequiredModifier reqmod = type as RequiredModifier;
+ if (reqmod != null)
+ {
+ TypeNode t = TypeNode.DeepStripModifiers(reqmod.ModifiedType, modifiers);
+ for (int i = 0; i < modifiers.Length; ++i)
+ {
+ if (reqmod.Modifier == modifiers[i])
+ {
+ // strip it
+ return t;
+ }
+ }
+ return RequiredModifier.For(reqmod.Modifier, t);
+ }
+ // For arrays and references, strip the inner type and then reconstruct the array or reference
+ ArrayType ar = type as ArrayType;
+ if (ar != null)
+ {
+ TypeNode t = TypeNode.DeepStripModifiers(ar.ElementType, modifiers);
+ return t.GetArrayType(1);
+ }
+ Reference rt = type as Reference;
+ if (rt != null)
+ {
+ TypeNode t = TypeNode.DeepStripModifiers(rt.ElementType, modifiers);
+ return t.GetReferenceType();
+ }
+ // strip template arguments
+ if (type.Template != null && type.TemplateArguments != null && type.TemplateArguments.Count > 0)
+ {
+ TypeNodeList strippedArgs = new TypeNodeList(type.TemplateArguments.Count);
+ for (int i = 0; i < type.TemplateArguments.Count; i++)
+ {
+ strippedArgs.Add(DeepStripModifiers(type.TemplateArguments[i], modifiers));
+ }
+ return type.Template.GetTemplateInstance(type, strippedArgs);
+ }
+ return type;
+ }
+#endif
+ public static bool HasModifier(TypeNode type, TypeNode modifier)
+ {
+ // Don't look under pointers or refs.
+ TypeModifier tmod = type as TypeModifier;
+ if (tmod != null)
+ {
+ if (tmod.Modifier == modifier) return true;
+ return TypeNode.HasModifier(tmod.ModifiedType, modifier);
+ }
+ return false;
+ }
+ public static TypeNode StripModifier(TypeNode type, TypeNode modifier)
+ {
+ // Don't strip under pointers or refs. We only strip top-level modifiers
+ TypeModifier tmod = type as TypeModifier;
+ if (tmod != null)
+ {
+ TypeNode et = TypeNode.StripModifier(tmod.ModifiedType, modifier);
+ //^ assert et != null;
+ if (tmod.Modifier == modifier) return et;
+ if (et == tmod.ModifiedType) return tmod;
+ if (tmod is OptionalModifier) return OptionalModifier.For(tmod.Modifier, et);
+ return RequiredModifier.For(tmod.Modifier, et);
+ }
+ return type;
+ }
+ /// <summary>
+ /// Needed whenever we change the id of an existing member
+ /// </summary>
+#if !MinimalReader
+ public
+#else
+ internal
+#endif
+ virtual void ClearMemberTable()
+ {
+ lock (this)
+ {
+ this.memberTable = null;
+ this.memberCount = 0;
+ }
+ }
+ protected virtual void UpdateMemberTable(int range)
+ //^ ensures this.memberTable != null;
+ {
+ MemberList thisMembers = this.Members;
+ lock (this)
+ {
+ if (this.memberTable == null) this.memberTable = new TrivialHashtable(32);
+ for (int i = this.memberCount; i < range; i++)
+ {
+ Member mem = thisMembers[i];
+ if (mem == null || mem.Name == null) continue;
+ MemberList members = (MemberList)this.memberTable[mem.Name.UniqueIdKey];
+ if (members == null) this.memberTable[mem.Name.UniqueIdKey] = members = new MemberList();
+ members.Add(mem);
+ }
+ this.memberCount = range;
+ this.constructors = null;
+ }
+ }
+ protected static MemberList WeedOutNonSpecialMethods(MemberList members, MethodFlags mask)
+ {
+ if (members == null) return null;
+ bool membersOK = true;
+ for (int i = 0, n = members.Count; i < n; i++)
+ {
+ Method m = members[i] as Method;
+ if (m == null || (m.Flags & mask) == 0)
+ {
+ membersOK = false; break;
+ }
+ }
+ if (membersOK) return members;
+ MemberList newMembers = new MemberList();
+ for (int i = 0, n = members.Count; i < n; i++)
+ {
+ Method m = members[i] as Method;
+ if (m == null || (m.Flags & mask) == 0) continue;
+ newMembers.Add(m);
+ }
+ return newMembers;
+ }
+#if !NoXml
+ public override void WriteDocumentation(XmlTextWriter xwriter)
+ {
+ base.WriteDocumentation(xwriter);
+ MemberList members = this.Members;
+ for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++)
+ {
+ Member mem = members[i];
+ if (mem == null) continue;
+ mem.WriteDocumentation(xwriter);
+ }
+ }
+#endif
+#if ExtendedRuntime
+ public TypeNode StripOptionalModifiers(out bool nonNull){
+ TypeNode t = this;
+ nonNull = false;
+ for(;;){
+ OptionalModifier m = t as OptionalModifier;
+ if (m == null)
+ break;
+ if (m.Modifier == SystemTypes.NonNullType)
+ nonNull = true;
+ t = m.ModifiedType;
+ }
+ return t;
+ }
+ public bool IsObjectReferenceType{
+ get{
+ bool nonNull;
+ TypeNode t = this.StripOptionalModifiers(out nonNull);
+ return t is Class || t is Interface || t is ArrayType || t is DelegateNode;
+ }
+ }
+#endif
+ public override string ToString()
+ {
+#if !FxCop
+ return this.GetFullUnmangledNameWithTypeParameters();
+#else
+ return base.ToString() + ":" + this.GetFullUnmangledNameWithTypeParameters();
+#endif
+ }
+#if FxCop
+ internal override void GetName(MemberFormat options, StringBuilder name)
+ {
+ GetName(options.Type, name);
+ }
+ internal virtual void GetName(TypeFormat options, StringBuilder name)
+ {
+ if (options.TypeName != TypeNameFormat.None)
+ {
+ if (this.DeclaringType != null && options.TypeName != TypeNameFormat.InnermostNested)
+ {
+ this.DeclaringType.GetName(options, name);
+ name.Append('+');
+ }
+ else if (options.TypeName == TypeNameFormat.FullyQualified && this.Namespace.Name.Length > 0)
+ {
+ name.Append(this.Namespace.Name);
+ name.Append('.');
+ }
+ string shortName = this.Name.Name;
+ int mangleChar = shortName.IndexOf(TargetPlatform.GenericTypeNamesMangleChar);
+ if (mangleChar != -1)
+ shortName = shortName.Substring(0, mangleChar);
+ name.Append(shortName);
+ }
+ TypeNodeList templateParameters = this.TemplateParameters;
+ if (this.Template != null) templateParameters = this.TemplateArguments;
+ if (templateParameters != null)
+ {
+ if (options.ShowGenericTypeArity)
+ {
+ name.Append(TargetPlatform.GenericTypeNamesMangleChar);
+ int parametersCount = templateParameters.Count;
+ name.Append(Convert.ToString(parametersCount, CultureInfo.InvariantCulture));
+ }
+ if (options.ShowGenericTypeParameterNames)
+ {
+ name.Append('<');
+ int parametersCount = templateParameters.Count;
+ for (int i = 0; i < parametersCount; ++i)
+ {
+ if (i > 0)
+ {
+ name.Append(',');
+ if (options.InsertSpacesBetweenTypeParameters) name.Append(' ');
+ }
+ templateParameters[i].GetName(options, name);
+ }
+ name.Append('>');
+ }
+ }
+ }
+#endif
+ }
+#if FxCop
+ public class ClassNode : TypeNode{
+#else
+ public class Class : TypeNode
+ {
+#endif
+ internal readonly static Class DoesNotExist = new Class();
+ internal readonly static Class Dummy = new Class();
+ internal Class baseClass;
+#if !MinimalReader
+ public Class BaseClassExpression;
+ public bool IsAbstractSealedContainerForStatics;
+#endif
+#if FxCop
+ public ClassNode()
+ : base(NodeType.Class){
+ }
+ public ClassNode(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
+ : base(NodeType.Class, provideNestedTypes, provideAttributes, provideMembers, handle){
+ }
+#else
+ public Class()
+ : base(NodeType.Class)
+ {
+ }
+ public Class(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
+ : base(NodeType.Class, provideNestedTypes, provideAttributes, provideMembers, handle)
+ {
+ }
+#endif
+#if !MinimalReader
+ public Class(Module declaringModule, TypeNode declaringType, AttributeList attributes, TypeFlags flags,
+ Identifier Namespace, Identifier name, Class baseClass, InterfaceList interfaces, MemberList members)
+ : base(declaringModule, declaringType, attributes, flags, Namespace, name, interfaces, members, NodeType.Class)
+ {
+ this.baseClass = baseClass;
+ }
+#endif
+ /// <summary>
+ /// The class from which this class has been derived. Null if this class is System.Object.
+ /// </summary>
+ public virtual Class BaseClass
+ {
+ get
+ {
+ return baseClass;
+ }
+ set
+ {
+ baseClass = value;
+ }
+ }
+#if !MinimalReader
+ public override void GetAbstractMethods(MethodList/*!*/ result)
+ {
+ if (!this.IsAbstract) return;
+ MethodList candidates = new MethodList();
+ if (this.BaseClass != null)
+ {
+ this.BaseClass.GetAbstractMethods(candidates);
+ for (int i = 0, n = candidates.Count; i < n; i++)
+ {
+ Method meth = candidates[i];
+ if (!this.ImplementsMethod(meth, false)) result.Add(meth);
+ }
+ }
+ //Add any abstract methods declared inside this class
+ MemberList members = this.Members;
+ for (int i = 0, n = members.Count; i < n; i++)
+ {
+ Method meth = members[i] as Method;
+ if (meth == null) continue;
+ if (meth.IsAbstract) result.Add(meth);
+ }
+ //For each interface, get abstract methods and keep those that are not implemented by this class or a base class
+ InterfaceList interfaces = this.Interfaces;
+ if (interfaces != null)
+ for (int i = 0, n = interfaces.Count; i < n; i++)
+ {
+ Interface iface = interfaces[i];
+ if (iface == null) continue;
+ MemberList imembers = iface.Members;
+ if (imembers == null) continue;
+ for (int j = 0, m = imembers.Count; j < m; j++)
+ {
+ Method meth = imembers[j] as Method;
+ if (meth == null) continue;
+ if (this.ImplementsExplicitly(meth)) continue;
+ if (this.ImplementsMethod(meth, true)) continue;
+ if (this.AlreadyInList(result, meth)) continue;
+ result.Add(meth);
+ }
+ }
+ }
+ protected bool AlreadyInList(MethodList list, Method method)
+ {
+ if (list == null) return false;
+ for (int i = 0, n = list.Count; i < n; i++)
+ {
+ if (list[i] == method) return true;
+ }
+ return false;
+ }
+#endif
+#if ExtendedRuntime
+ public bool IsGuarded{
+ get{
+ Field f = this.GetField(Identifier.For("SpecSharp::frameGuard"));
+ return f != null;
+ }
+ }
+#endif
+ }
+#if !MinimalReader
+ public class ClosureClass : Class
+ {
+ public ClosureClass()
+ {
+ }
+ }
+ /// <summary>
+ /// 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.
+ /// </summary>
+ //TODO: use delegation rather than inheritance to achieve this
+ public class Scope : Class
+ {
+ public Scope()
+ {
+ }
+ public Scope(Scope outerScope)
+ {
+ this.OuterScope = outerScope;
+ }
+ protected Scope outerScope;
+ public SourceContext LexicalSourceExtent;
+ public Scope OuterScope
+ {
+ get
+ {
+ if (this.outerScope == null)
+ this.outerScope = (Scope)this.baseClass;
+ return this.outerScope;
+ }
+ set
+ {
+ this.baseClass = this.outerScope = value;
+ }
+ }
+ public virtual TypeNode GetType(Identifier typeName)
+ {
+ return this.GetNestedType(typeName);
+ }
+ }
+ public class TypeScope : Scope
+ {
+ public TypeNode Type;
+ public TypeScope() { }
+ public TypeScope(Scope parentScope, TypeNode/*!*/ type)
+ {
+ this.baseClass = parentScope;
+ this.DeclaringModule = type.DeclaringModule;
+ this.Type = type;
+ if (type != null && type.PartiallyDefines != null) this.Type = type.PartiallyDefines;
+ this.templateParameters = type.TemplateParameters;
+ if (type != null)
+ this.LexicalSourceExtent = type.SourceContext;
+ }
+ public override MemberList/*!*/ GetMembersNamed(Identifier name)
+ {
+ TypeNode t = this.Type;
+ MemberList result = null;
+ while (t != null)
+ {
+ result = t.GetMembersNamed(name);
+ if (result.Count > 0) return result;
+ t = t.BaseType;
+ }
+ if (result != null) return result;
+ return new MemberList(0);
+ }
+ public override MemberList Members
+ {
+ get
+ {
+ return this.Type.Members;
+ }
+ set
+ {
+ base.Members = value;
+ }
+ }
+ }
+ public class MethodScope : Scope
+ {
+ protected Class closureClass;
+ public virtual Class ClosureClass
+ {
+ get
+ {
+ //if (this.DeclaringMethod == null) return null;
+ Class c = this.closureClass;
+ if (c == null)
+ {
+ c = this.closureClass = new ClosureClass();
+ c.Name = Identifier.For("closure:" + this.UniqueKey);
+ c.BaseClass = CoreSystemTypes.Object;
+ Class bclass = this.BaseClass;
+ c.DeclaringModule = bclass.DeclaringModule;
+ TypeScope tscope = bclass as TypeScope;
+ if (tscope != null)
+ c.DeclaringType = tscope.Type;
+ else
+ {
+ MethodScope mscope = bclass as MethodScope;
+ if (mscope != null)
+ c.DeclaringType = mscope.ClosureClass;
+ else
+ c.DeclaringType = ((BlockScope)bclass).ClosureClass;
+ }
+ c.IsGeneric = c.DeclaringType.IsGeneric || this.DeclaringMethod.IsGeneric;
+ c.TemplateParameters = this.CopyMethodTemplateParameters(c.DeclaringModule, c.DeclaringType);
+ c.Flags = TypeFlags.NestedPrivate | TypeFlags.SpecialName | TypeFlags.Sealed;
+ c.Interfaces = new InterfaceList(0);
+ if (this.ThisType != null)
+ {
+ Field f = new Field(c, null, FieldFlags.CompilerControlled | FieldFlags.SpecialName, StandardIds.ThisValue, this.ThisType, null);
+ this.ThisField = f;
+ c.Members.Add(f);
+ }
+ }
+ return c;
+ }
+ }
+ private TypeNodeList CopyMethodTemplateParameters(Module/*!*/ module, TypeNode/*!*/ type)
+ //^ requires this.DeclaringMethod != null;
+ {
+ TypeNodeList methTemplParams = this.DeclaringMethod.TemplateParameters;
+ if (methTemplParams == null || methTemplParams.Count == 0) return null;
+ this.tpDup = new TemplateParameterDuplicator(module, type);
+ return this.tpDup.VisitTypeParameterList(methTemplParams);
+ }
+ private TemplateParameterDuplicator tpDup;
+ private class TemplateParameterDuplicator : Duplicator
+ {
+ public TemplateParameterDuplicator(Module/*!*/ module, TypeNode/*!*/ type)
+ : base(module, type)
+ {
+ }
+
+ public override TypeNode VisitTypeParameter(TypeNode typeParameter)
+ {
+ if (typeParameter == null) return null;
+ TypeNode result = (TypeNode)this.DuplicateFor[typeParameter.UniqueKey];
+ if (result != null) return result;
+ MethodTypeParameter mtp = typeParameter as MethodTypeParameter;
+ if (mtp != null)
+ {
+ TypeParameter tp = new TypeParameter();
+ this.DuplicateFor[typeParameter.UniqueKey] = tp;
+ tp.Name = mtp.Name;
+ tp.Interfaces = this.VisitInterfaceReferenceList(mtp.Interfaces);
+ tp.TypeParameterFlags = mtp.TypeParameterFlags;
+ tp.DeclaringModule = mtp.DeclaringModule;
+ tp.DeclaringMember = this.TargetType;
+ result = tp;
+ }
+ else
+ {
+ MethodClassParameter mcp = typeParameter as MethodClassParameter;
+ if (mcp != null)
+ {
+ ClassParameter cp = new ClassParameter();
+ this.DuplicateFor[typeParameter.UniqueKey] = cp;
+ cp.Name = mcp.Name;
+ cp.BaseClass = (Class)this.VisitTypeReference(mcp.BaseClass);
+ cp.Interfaces = this.VisitInterfaceReferenceList(mcp.Interfaces);
+ cp.TypeParameterFlags = mcp.TypeParameterFlags;
+ cp.DeclaringModule = mcp.DeclaringModule;
+ cp.DeclaringMember = this.TargetType;
+ result = cp;
+ }
+ }
+ if (result == null) return typeParameter;
+ return result;
+ }
+ public override TypeNode VisitTypeReference(TypeNode type)
+ {
+ TypeNode result = base.VisitTypeReference(type);
+ if (result == type && (type is MethodClassParameter || type is MethodTypeParameter))
+ return this.VisitTypeParameter(type);
+ return result;
+ }
+ }
+ public virtual Class ClosureClassTemplateInstance
+ {
+ get
+ {
+ if (this.closureClassTemplateInstance == null)
+ {
+ if (this.DeclaringMethod == null || !this.DeclaringMethod.IsGeneric)
+ this.closureClassTemplateInstance = this.ClosureClass;
+ else
+ this.closureClassTemplateInstance = (Class)this.ClosureClass.GetTemplateInstance(this.DeclaringMethod.DeclaringType, this.DeclaringMethod.TemplateParameters);
+ }
+ return this.closureClassTemplateInstance;
+ }
+ }
+ Class closureClassTemplateInstance;
+ public TypeNode FixTypeReference(TypeNode type)
+ {
+ if (this.tpDup == null) return type;
+ return this.tpDup.VisitTypeReference(type);
+ }
+
+ public virtual Boolean CapturedForClosure
+ {
+ get
+ {
+ return this.closureClass != null;
+ }
+ }
+ public UsedNamespaceList UsedNamespaces;
+ public Field ThisField;
+ public TypeNode ThisType;
+ public TypeNode ThisTypeInstance;
+ public Method DeclaringMethod;
+ public MethodScope() { }
+ public MethodScope(Class/*!*/ parentScope, UsedNamespaceList usedNamespaces)
+ : this(parentScope, usedNamespaces, null)
+ {
+ }
+ public MethodScope(Class/*!*/ parentScope, UsedNamespaceList usedNamespaces, Method method)
+ {
+ this.baseClass = parentScope;
+ this.UsedNamespaces = usedNamespaces;
+ this.DeclaringModule = parentScope.DeclaringModule;
+ this.DeclaringMethod = method;
+ if (method != null && (method.Flags & MethodFlags.Static) == 0)
+ this.ThisType = this.ThisTypeInstance = method.DeclaringType;
+ if (method != null)
+ this.LexicalSourceExtent = method.SourceContext;
+ }
+ }
+ public class BlockScope : Scope
+ {
+ public Block AssociatedBlock;
+ public bool MembersArePinned;
+ public virtual Class ClosureClass
+ {
+ get
+ {
+ BlockScope bscope = this.BaseClass as BlockScope;
+ if (bscope != null) return bscope.ClosureClass;
+ MethodScope mscope = this.BaseClass as MethodScope;
+ if (mscope != null) return mscope.ClosureClass;
+ return ((TypeScope)this.BaseClass).Type as Class;
+ }
+ }
+ public virtual Boolean CapturedForClosure
+ {
+ get
+ {
+ BlockScope bscope = this.BaseClass as BlockScope;
+ if (bscope != null) return bscope.CapturedForClosure;
+ MethodScope mscope = this.BaseClass as MethodScope;
+ if (mscope != null) return mscope.CapturedForClosure;
+ return false;
+ }
+ }
+ public BlockScope()
+ {
+ }
+ public BlockScope(Scope/*!*/ parentScope, Block associatedBlock)
+ {
+ this.AssociatedBlock = associatedBlock;
+ if (associatedBlock != null)
+ {
+ associatedBlock.HasLocals = true; //TODO: set only if there really are locals
+ associatedBlock.Scope = this;
+ }
+ this.baseClass = parentScope;
+ this.DeclaringModule = parentScope.DeclaringModule;
+ if (associatedBlock != null)
+ this.LexicalSourceExtent = associatedBlock.SourceContext;
+ }
+ }
+ public class AttributeScope : Scope
+ {
+ public AttributeNode AssociatedAttribute;
+ public AttributeScope(Scope parentScope, AttributeNode associatedAttribute)
+ {
+ this.AssociatedAttribute = associatedAttribute;
+ this.baseClass = parentScope;
+ if (associatedAttribute != null)
+ this.LexicalSourceExtent = associatedAttribute.SourceContext;
+ }
+ }
+ public class NamespaceScope : Scope
+ {
+ public Namespace AssociatedNamespace;
+ public Module AssociatedModule;
+ public TrivialHashtable AliasedType;
+ public TrivialHashtable AliasedNamespace;
+ protected TrivialHashtable/*!*/ aliasFor = new TrivialHashtable();
+ protected TrivialHashtable/*!*/ typeFor = new TrivialHashtable();
+ protected TrivialHashtable/*!*/ namespaceFor = new TrivialHashtable();
+ protected TrivialHashtable/*!*/ nestedNamespaceFullName = new TrivialHashtable();
+ protected readonly static AliasDefinition/*!*/ noSuchAlias = new AliasDefinition();
+
+ public NamespaceScope()
+ {
+ }
+ public NamespaceScope(Scope outerScope, Namespace associatedNamespace, Module associatedModule)
+ : base(outerScope)
+ {
+ //^ base;
+ this.AssociatedNamespace = associatedNamespace;
+ this.AssociatedModule = associatedModule;
+ this.DeclaringModule = associatedModule; //TODO: make this go away
+ if (associatedNamespace != null)
+ this.LexicalSourceExtent = associatedNamespace.SourceContext;
+ }
+ public virtual AliasDefinition GetAliasFor(Identifier name)
+ {
+ if (name == null || this.AssociatedNamespace == null || this.AssociatedModule == null || this.aliasFor == null)
+ {
+ Debug.Assert(false); return null;
+ }
+ AliasDefinition alias = (AliasDefinition)this.aliasFor[name.UniqueIdKey];
+ if (alias == noSuchAlias) return null;
+ if (alias != null) return alias;
+ //Check if there is an alias with this uri
+ Scope scope = this;
+ while (scope != null)
+ {
+ NamespaceScope nsScope = scope as NamespaceScope;
+ if (nsScope != null && nsScope.AssociatedNamespace != null)
+ {
+ AliasDefinitionList aliases = nsScope.AssociatedNamespace.AliasDefinitions;
+ if (aliases != null)
+ for (int i = 0, n = aliases.Count; i < n; i++)
+ {
+ AliasDefinition aliasDef = aliases[i];
+ if (aliasDef == null || aliasDef.Alias == null) continue;
+ if (aliasDef.Alias.UniqueIdKey == name.UniqueIdKey) { alias = aliasDef; goto done; }
+ }
+ }
+ scope = scope.OuterScope;
+ }
+ done:
+ if (alias != null)
+ this.aliasFor[name.UniqueIdKey] = alias;
+ else
+ this.aliasFor[name.UniqueIdKey] = noSuchAlias;
+ return alias;
+ }
+ public virtual AliasDefinition GetConflictingAlias(Identifier name)
+ {
+ if (name == null || this.typeFor == null || this.AssociatedNamespace == null || this.AssociatedModule == null)
+ {
+ Debug.Assert(false); return null;
+ }
+ TypeNode type = this.AssociatedModule.GetType(this.AssociatedNamespace.FullNameId, name);
+ if (type != null)
+ {
+ AliasDefinitionList aliases = this.AssociatedNamespace.AliasDefinitions;
+ for (int i = 0, n = aliases == null ? 0 : aliases.Count; i < n; i++)
+ {
+ //^ assert aliases != null;
+ AliasDefinition aliasDef = aliases[i];
+ if (aliasDef == null || aliasDef.Alias == null) continue;
+ if (aliasDef.Alias.UniqueIdKey == name.UniqueIdKey) return aliasDef;
+ }
+ }
+ Scope scope = this;
+ while (scope != null)
+ {
+ NamespaceScope outerScope = scope.OuterScope as NamespaceScope;
+ if (outerScope != null) return outerScope.GetConflictingAlias(name);
+ scope = scope.OuterScope;
+ }
+ return null;
+ }
+ public virtual Identifier GetUriFor(Identifier name)
+ {
+ AliasDefinition aliasDef = this.GetAliasFor(name);
+ if (aliasDef == null) return null;
+ return aliasDef.AliasedUri;
+ }
+ public virtual Identifier GetNamespaceFullNameFor(Identifier name)
+ {
+ if (name == null || this.AssociatedNamespace == null || this.AssociatedModule == null || this.nestedNamespaceFullName == null)
+ {
+ Debug.Assert(false); return null;
+ }
+ Identifier fullName = (Identifier)this.nestedNamespaceFullName[name.UniqueIdKey];
+ if (fullName == Identifier.Empty) return null;
+ if (fullName != null) return fullName;
+ //Check if there is an alias with this namespace
+ AliasDefinition aliasDef = this.GetAliasFor(name);
+ if (aliasDef != null && aliasDef.AliasedUri == null && aliasDef.AliasedType == null)
+ return aliasDef.AliasedExpression as Identifier;
+ //Check if module has a type with namespace equal to this namespace + name
+ fullName = name;
+ if (this.AssociatedNamespace.Name != null && this.AssociatedNamespace.Name.UniqueIdKey != Identifier.Empty.UniqueIdKey)
+ fullName = Identifier.For(this.AssociatedNamespace.FullName + "." + name);
+ if (this.AssociatedModule.IsValidNamespace(fullName))
+ {
+ this.namespaceFor[fullName.UniqueIdKey] = new TrivialHashtable();
+ goto returnFullName;
+ }
+ // If an inner type shadows an outer namespace, don't return the namespace
+ if (this.AssociatedModule.IsValidTypeName(this.AssociatedNamespace.Name, name)) { return null; }
+ AssemblyReferenceList arefs = this.AssociatedModule.AssemblyReferences;
+ for (int i = 0, n = arefs == null ? 0 : arefs.Count; i < n; i++)
+ {
+ AssemblyReference ar = arefs[i];
+ if (ar == null || ar.Assembly == null) continue;
+ if (ar.Assembly.IsValidNamespace(fullName)) goto returnFullName;
+ // If an inner type shadows an outer namespace, don't return the namespace
+ if (ar.Assembly.IsValidTypeName(this.AssociatedNamespace.Name, name)) { return null; }
+ }
+ ModuleReferenceList mrefs = this.AssociatedModule.ModuleReferences;
+ if (mrefs != null)
+ for (int i = 0, n = mrefs.Count; i < n; i++)
+ {
+ ModuleReference mr = mrefs[i];
+ if (mr == null || mr.Module == null) continue;
+ if (mr.Module.IsValidNamespace(fullName)) goto returnFullName;
+ // If an inner type shadows an outer namespace, don't return the namespace
+ if (mr.Module.IsValidTypeName(this.AssociatedNamespace.Name, name)) { return null; }
+ }
+ Scope scope = this.OuterScope;
+ while (scope != null && !(scope is NamespaceScope)) scope = scope.OuterScope;
+ if (scope != null) return ((NamespaceScope)scope).GetNamespaceFullNameFor(name);
+ return null;
+ returnFullName:
+ this.nestedNamespaceFullName[name.UniqueIdKey] = fullName;
+ return fullName;
+ }
+ /// <summary>
+ /// Search this namespace for a type with this name nested in the given namespace. Also considers used name spaces.
+ /// If more than one type is found, a list is returned in duplicates.
+ /// </summary>
+ public virtual TypeNode GetType(Identifier Namespace, Identifier name, out TypeNodeList duplicates)
+ {
+ duplicates = null;
+ if (Namespace == null || name == null || this.AssociatedNamespace == null || this.AssociatedModule == null)
+ {
+ Debug.Assert(false); return null;
+ }
+ if (this.namespaceFor == null)
+ {
+ Debug.Assert(false);
+ this.namespaceFor = new TrivialHashtable();
+ }
+ TrivialHashtable typeFor = (TrivialHashtable)this.namespaceFor[Namespace.UniqueIdKey];
+ if (typeFor == null) this.namespaceFor[Namespace.UniqueIdKey] = typeFor = new TrivialHashtable();
+ TypeNode result = (TypeNode)typeFor[name.UniqueIdKey];
+ if (result == Class.DoesNotExist) return null;
+ if (result != null) return result;
+ //If the associated module declares a type with the given name in a nested namespace, it wins
+ Scope scope = this;
+ while (scope != null)
+ {
+ NamespaceScope nsScope = scope as NamespaceScope;
+ if (nsScope != null && nsScope.AssociatedNamespace != null)
+ {
+ Identifier nestedNamespace = Namespace;
+ if (nsScope.AssociatedNamespace.FullNameId != null && nsScope.AssociatedNamespace.FullNameId.UniqueIdKey != Identifier.Empty.UniqueIdKey)
+ nestedNamespace = Identifier.For(nsScope.AssociatedNamespace.FullName + "." + Namespace);
+ result = this.AssociatedModule.GetType(nestedNamespace, name);
+ if (result != null) break;
+ }
+ scope = scope.OuterScope;
+ }
+ if (result == null)
+ {
+ //Now get into situations where there might be duplicates.
+ duplicates = new TypeNodeList();
+ //Check the used namespaces of this and outer namespace scopes
+ TrivialHashtable alreadyUsed = new TrivialHashtable();
+ scope = this;
+ while (scope != null)
+ {
+ NamespaceScope nsScope = scope as NamespaceScope;
+ if (nsScope != null && nsScope.AssociatedNamespace != null)
+ {
+ UsedNamespaceList usedNamespaces = nsScope.AssociatedNamespace.UsedNamespaces;
+ int n = usedNamespaces == null ? 0 : usedNamespaces.Count;
+ if (usedNamespaces != null)
+ for (int i = 0; i < n; i++)
+ {
+ UsedNamespace usedNs = usedNamespaces[i];
+ if (usedNs == null || usedNs.Namespace == null) continue;
+ int key = usedNs.Namespace.UniqueIdKey;
+ if (alreadyUsed[key] != null) continue;
+ alreadyUsed[key] = usedNs.Namespace;
+ Identifier usedNestedNamespace = Identifier.For(usedNs.Namespace + "." + Namespace);
+ result = this.AssociatedModule.GetType(usedNestedNamespace, name);
+ if (result != null) duplicates.Add(result);
+ }
+ }
+ scope = scope.OuterScope;
+ }
+ if (duplicates.Count > 0) result = duplicates[0];
+ }
+ if (result == null)
+ {
+ //The associated module does not have a type by this name, so check its referenced modules and assemblies
+ int numDups = 0;
+ //Check this namespace and outer namespaces
+ scope = this;
+ while (scope != null && result == null)
+ {
+ NamespaceScope nsScope = scope as NamespaceScope;
+ if (nsScope != null && nsScope.AssociatedNamespace != null)
+ {
+ Identifier nestedNamespace = Namespace;
+ if (nsScope.AssociatedNamespace.FullNameId != null && nsScope.AssociatedNamespace.FullNameId.UniqueIdKey != Identifier.Empty.UniqueIdKey)
+ nestedNamespace = Identifier.For(nsScope.AssociatedNamespace.FullName + "." + Namespace);
+ nsScope.GetReferencedTypes(nestedNamespace, name, duplicates);
+ numDups = duplicates.Count;
+ for (int i = numDups - 1; i >= 0; i--)
+ {
+ TypeNode dup = duplicates[i];
+ if (dup == null || !dup.IsPublic) numDups--;
+ result = dup;
+ }
+ }
+ scope = scope.OuterScope;
+ }
+ if (numDups == 0)
+ {
+ if (duplicates.Count > 0) duplicates = new TypeNodeList();
+ //Check the used namespaces of this and outer namespace scopes
+ TrivialHashtable alreadyUsed = new TrivialHashtable();
+ scope = this;
+ while (scope != null)
+ {
+ NamespaceScope nsScope = scope as NamespaceScope;
+ if (nsScope != null && nsScope.AssociatedNamespace != null)
+ {
+ UsedNamespaceList usedNamespaces = this.AssociatedNamespace.UsedNamespaces;
+ int n = usedNamespaces == null ? 0 : usedNamespaces.Count;
+ if (usedNamespaces != null)
+ for (int i = 0; i < n; i++)
+ {
+ UsedNamespace usedNs = usedNamespaces[i];
+ if (usedNs == null) continue;
+ int key = usedNs.Namespace.UniqueIdKey;
+ if (alreadyUsed[key] != null) continue;
+ alreadyUsed[key] = usedNs.Namespace;
+ Identifier usedNestedNamespace = Identifier.For(usedNs.Namespace + "." + Namespace);
+ this.GetReferencedTypes(usedNestedNamespace, name, duplicates);
+ }
+ }
+ scope = scope.OuterScope;
+ }
+ numDups = duplicates.Count;
+ for (int i = numDups - 1; i >= 0; i--)
+ {
+ TypeNode dup = duplicates[i];
+ if (dup == null || !dup.IsPublic) numDups--;
+ result = dup;
+ }
+ }
+ if (numDups <= 1) duplicates = null;
+ }
+ if (result == null)
+ typeFor[name.UniqueIdKey] = Class.DoesNotExist;
+ else
+ typeFor[name.UniqueIdKey] = result;
+ return result;
+ }
+ /// <summary>
+ /// Searches this namespace for a type with this name. Also considers aliases and used name spaces, including those of outer namespaces.
+ /// If more than one type is found, a list is returned in duplicates. Types defined in the associated
+ /// module mask types defined in referenced modules and assemblies. Results are cached and duplicates are returned only when
+ /// there is a cache miss.
+ /// </summary>
+ public virtual TypeNode GetType(Identifier name, out TypeNodeList duplicates)
+ {
+ return this.GetType(name, out duplicates, false);
+ }
+ public virtual TypeNode GetType(Identifier name, out TypeNodeList duplicates, bool returnNullIfHiddenByNestedNamespace)
+ {
+ duplicates = null;
+ if (name == null || this.typeFor == null || this.AssociatedNamespace == null || this.AssociatedModule == null)
+ {
+ Debug.Assert(false); return null;
+ }
+ AssemblyNode associatedAssembly = this.AssociatedModule as AssemblyNode;
+ TypeNode result = (TypeNode)this.typeFor[name.UniqueIdKey];
+ if (result == Class.DoesNotExist) return null;
+ if (result != null) return result;
+ //If the associated module declares a type with the given name in this namespace, it wins
+ result = this.AssociatedModule.GetType(this.AssociatedNamespace.FullNameId, name);
+ if (result == null && returnNullIfHiddenByNestedNamespace)
+ {
+ //Do not proceed to outer namespaces or look at aliases. The nested namespace hides these.
+ Identifier fullName = name;
+ if (this.AssociatedNamespace.FullName != null && this.AssociatedNamespace.Name.UniqueIdKey != Identifier.Empty.UniqueIdKey)
+ fullName = Identifier.For(this.AssociatedNamespace.FullName + "." + name);
+ if (this.AssociatedModule.IsValidNamespace(fullName))
+ result = Class.DoesNotExist;
+ }
+ if (result == null)
+ {
+ //If the namespace (or an outer namespace) has an alias definition with this name it wins. (Expected to be mutually exclusive with above.)
+ Scope scope = this;
+ while (scope != null && result == null)
+ {
+ NamespaceScope nsScope = scope as NamespaceScope;
+ if (nsScope != null && nsScope.AliasedType != null)
+ result = (TypeNode)nsScope.AliasedType[name.UniqueIdKey];
+ if (result == null && returnNullIfHiddenByNestedNamespace && nsScope != null &&
+ nsScope.AliasedNamespace != null && nsScope.AliasedNamespace[name.UniqueIdKey] != null)
+ result = Class.DoesNotExist;
+ scope = scope.OuterScope;
+ }
+ }
+ if (result == null)
+ {
+ //Now get into situations where there might be duplicates.
+ duplicates = new TypeNodeList();
+ //Check the used namespaces of this and outer namespace scopes
+ TrivialHashtable alreadyUsed = new TrivialHashtable();
+ Scope scope = this;
+ while (scope != null)
+ {
+ NamespaceScope nsScope = scope as NamespaceScope;
+ if (nsScope != null && nsScope.AssociatedNamespace != null && nsScope.AssociatedModule != null)
+ {
+ UsedNamespaceList usedNamespaces = nsScope.AssociatedNamespace.UsedNamespaces;
+ int n = usedNamespaces == null ? 0 : usedNamespaces.Count;
+ if (usedNamespaces != null)
+ for (int i = 0; i < n; i++)
+ {
+ UsedNamespace usedNs = usedNamespaces[i];
+ if (usedNs == null || usedNs.Namespace == null) continue;
+ int key = usedNs.Namespace.UniqueIdKey;
+ if (alreadyUsed[key] != null) continue;
+ alreadyUsed[key] = usedNs.Namespace;
+ result = this.AssociatedModule.GetType(usedNs.Namespace, name);
+ //^ assert duplicates != null;
+ if (result != null) duplicates.Add(result);
+ }
+ }
+ if (returnNullIfHiddenByNestedNamespace) break;
+ scope = scope.OuterScope;
+ }
+ if (duplicates.Count > 0) result = duplicates[0];
+ }
+ if (result == null)
+ //First see if the the current module has a class by this name in the empty namespace
+ result = this.AssociatedModule.GetType(Identifier.Empty, name);
+ if (result == null)
+ {
+ //The associated module does not have a type by this name, so check its referenced modules and assemblies
+ //First check this namespace
+ this.GetReferencedTypes(this.AssociatedNamespace.FullNameId, name, duplicates);
+ int numDups = duplicates.Count;
+ if (numDups == 1)
+ {
+ result = duplicates[0];
+ if (this.IsNotAccessible(associatedAssembly, result)) { numDups--; result = null; }
+ }
+ else
+ {
+ for (int i = numDups - 1; i >= 0; i--)
+ {
+ TypeNode dup = duplicates[i];
+ if (this.IsNotAccessible(associatedAssembly, dup)) { numDups--; continue; }
+ result = dup;
+ }
+ if (numDups == 0 && duplicates.Count > 0)
+ {
+ result = duplicates[0];
+ numDups = duplicates.Count;
+ }
+ }
+ if (numDups == 0)
+ {
+ if (duplicates.Count > 0) duplicates = new TypeNodeList();
+ //Check the used namespaces of this and outer namespace scopes
+ TrivialHashtable alreadyUsed = new TrivialHashtable();
+ Scope scope = this;
+ while (scope != null)
+ {
+ NamespaceScope nsScope = scope as NamespaceScope;
+ if (nsScope != null)
+ {
+ UsedNamespaceList usedNamespaces = nsScope.AssociatedNamespace.UsedNamespaces;
+ int n = usedNamespaces == null ? 0 : usedNamespaces.Count;
+ if (usedNamespaces != null)
+ for (int i = 0; i < n; i++)
+ {
+ UsedNamespace usedNs = usedNamespaces[i];
+ if (usedNs == null || usedNs.Namespace == null) continue;
+ int key = usedNs.Namespace.UniqueIdKey;
+ if (alreadyUsed[key] != null) continue;
+ alreadyUsed[key] = usedNs.Namespace;
+ this.GetReferencedTypes(usedNs.Namespace, name, duplicates);
+ }
+ }
+ scope = scope.OuterScope;
+ if (returnNullIfHiddenByNestedNamespace) break;
+ }
+ numDups = duplicates.Count;
+ for (int i = numDups - 1; i >= 0; i--)
+ {
+ TypeNode dup = duplicates[i];
+ if (this.IsNotAccessible(associatedAssembly, dup))
+ {
+ numDups--; continue;
+ }
+ result = dup;
+ }
+ }
+ if (numDups == 0)
+ {
+ if (duplicates.Count > 0) duplicates = new TypeNodeList();
+ this.GetReferencedTypes(Identifier.Empty, name, duplicates);
+ numDups = duplicates.Count;
+ for (int i = numDups - 1; i >= 0; i--)
+ {
+ TypeNode dup = duplicates[i];
+ if (this.IsNotAccessible(associatedAssembly, dup))
+ {
+ numDups--; continue;
+ }
+ result = dup;
+ }
+ }
+ if (numDups <= 1) duplicates = null;
+ }
+ if (result == null)
+ this.typeFor[name.UniqueIdKey] = Class.DoesNotExist;
+ else
+ this.typeFor[name.UniqueIdKey] = result;
+ if (result == Class.DoesNotExist) return null;
+ if (duplicates != null && duplicates.Count > 1 && this.AssociatedNamespace != null && this.AssociatedNamespace.Name != null && this.AssociatedNamespace.Name.Name != null)
+ {
+ result = null;
+ for (int i = 0, n = duplicates.Count; i < n; i++)
+ {
+ TypeNode t = duplicates[i];
+ if (t == null || t.Namespace == null) continue;
+ if (this.AssociatedNamespace.Name.Name.StartsWith(t.Namespace.Name))
+ {
+ if (result != null)
+ {
+ result = null;
+ break;
+ }
+ result = t;
+ }
+ }
+ if (result != null)
+ duplicates = null;
+ else
+ result = duplicates[0];
+ }
+ return result;
+ }
+ private bool IsNotAccessible(AssemblyNode associatedAssembly, TypeNode dup)
+ {
+ if (dup == null) return false;
+ return !dup.IsPublic && (associatedAssembly == null ||
+ !associatedAssembly.MayAccessInternalTypesOf(dup.DeclaringModule as AssemblyNode)) && !this.AssociatedModule.ContainsModule(dup.DeclaringModule);
+ }
+ /// <summary>
+ /// Searches the module and assembly references of the associated module to find types
+ /// </summary>
+ public virtual void GetReferencedTypes(Identifier Namespace, Identifier name, TypeNodeList types)
+ {
+ if (Namespace == null || name == null || types == null || this.AssociatedModule == null) { Debug.Assert(false); return; }
+ AssemblyReferenceList arefs = this.AssociatedModule.AssemblyReferences;
+ for (int i = 0, n = arefs == null ? 0 : arefs.Count; i < n; i++)
+ {
+ AssemblyReference ar = arefs[i];
+ if (ar == null || ar.Assembly == null) continue;
+ TypeNode t = ar.Assembly.GetType(Namespace, name);
+ if (t == null) continue;
+ //TODO: deal with type forwarding
+ types.Add(t);
+ }
+ ModuleReferenceList mrefs = this.AssociatedModule.ModuleReferences;
+ if (mrefs != null)
+ for (int i = 0, n = mrefs.Count; i < n; i++)
+ {
+ ModuleReference mr = mrefs[i];
+ if (mr == null || mr.Module == null) continue;
+ TypeNode t = mr.Module.GetType(Namespace, name);
+ if (t == null) continue;
+ types.Add(t);
+ }
+ }
+ }
+#endif
+ public class DelegateNode : TypeNode
+ {
+ internal static readonly DelegateNode/*!*/ Dummy = new DelegateNode();
+ protected ParameterList parameters;
+ public virtual ParameterList Parameters
+ {
+ get
+ {
+ ParameterList pList = this.parameters;
+ if (pList == null)
+ {
+ MemberList members = this.Members; //Evaluate for side effect
+ if (members != null) members = null;
+ lock (this)
+ {
+ if (this.parameters != null) return this.parameters;
+ MemberList invokers = this.GetMembersNamed(StandardIds.Invoke);
+ for (int i = 0, n = invokers.Count; i < n; i++)
+ {
+ Method m = invokers[i] as Method;
+ if (m == null) continue;
+ this.parameters = pList = m.Parameters;
+ this.returnType = m.ReturnType;
+ break;
+ }
+ }
+ }
+ return pList;
+ }
+ set
+ {
+ this.parameters = value;
+ }
+ }
+ protected TypeNode returnType;
+ public virtual TypeNode ReturnType
+ {
+ get
+ {
+ TypeNode rt = this.returnType;
+ if (rt == null)
+ {
+ ParameterList pars = this.Parameters; //Evaluate for side effect
+ if (pars != null) pars = null;
+ rt = this.returnType;
+ }
+ return rt;
+ }
+ set
+ {
+ this.returnType = value;
+ }
+ }
+#if !MinimalReader
+ public TypeNode ReturnTypeExpression;
+#endif
+ public DelegateNode()
+ : base(NodeType.DelegateNode)
+ {
+ }
+ public DelegateNode(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
+ : base(NodeType.DelegateNode, provideNestedTypes, provideAttributes, provideMembers, handle)
+ {
+ }
+#if !MinimalReader
+ public DelegateNode(Module declaringModule, TypeNode declaringType, AttributeList attributes, TypeFlags flags,
+ Identifier Namespace, Identifier name, TypeNode returnType, ParameterList parameters)
+ : base(declaringModule, declaringType, attributes, flags, Namespace, name, null, null, NodeType.DelegateNode)
+ {
+ this.parameters = parameters;
+ this.returnType = returnType;
+ }
+ private bool membersAlreadyProvided;
+ public virtual void ProvideMembers()
+ {
+ if (this.membersAlreadyProvided) return;
+ this.membersAlreadyProvided = true;
+ this.memberCount = 0;
+ MemberList members = this.members = new MemberList();
+ //ctor
+ ParameterList parameters = new ParameterList(2);
+ parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.Object, CoreSystemTypes.Object, null, null));
+ parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.Method, CoreSystemTypes.IntPtr, null, null));
+ InstanceInitializer ctor = new InstanceInitializer(this, null, parameters, null);
+ ctor.Flags |= MethodFlags.Public | MethodFlags.HideBySig;
+ ctor.CallingConvention = CallingConventionFlags.HasThis;
+ ctor.ImplFlags = MethodImplFlags.Runtime;
+ members.Add(ctor);
+ //Invoke
+ Method invoke = new Method(this, null, StandardIds.Invoke, this.Parameters, this.ReturnType, null);
+ invoke.Flags = MethodFlags.Public | MethodFlags.HideBySig | MethodFlags.Virtual;
+ invoke.CallingConvention = CallingConventionFlags.HasThis;
+ invoke.ImplFlags = MethodImplFlags.Runtime;
+ members.Add(invoke);
+ //BeginInvoke
+ ParameterList dparams = this.parameters;
+ int n = dparams == null ? 0 : dparams.Count;
+ parameters = new ParameterList(n + 2);
+ for (int i = 0; i < n; i++)
+ {
+ //^ assert dparams != null;
+ Parameter p = dparams[i];
+ if (p == null) continue;
+ parameters.Add((Parameter)p.Clone());
+ }
+ parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.callback, SystemTypes.AsyncCallback, null, null));
+ parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.Object, CoreSystemTypes.Object, null, null));
+ Method beginInvoke = new Method(this, null, StandardIds.BeginInvoke, parameters, SystemTypes.IASyncResult, null);
+ beginInvoke.Flags = MethodFlags.Public | MethodFlags.HideBySig | MethodFlags.NewSlot | MethodFlags.Virtual;
+ beginInvoke.CallingConvention = CallingConventionFlags.HasThis;
+ beginInvoke.ImplFlags = MethodImplFlags.Runtime;
+ members.Add(beginInvoke);
+ //EndInvoke
+ parameters = new ParameterList(1);
+ for (int i = 0; i < n; i++)
+ {
+ Parameter p = dparams[i];
+ if (p == null || p.Type == null || !(p.Type is Reference)) continue;
+ parameters.Add((Parameter)p.Clone());
+ }
+ parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.result, SystemTypes.IASyncResult, null, null));
+ Method endInvoke = new Method(this, null, StandardIds.EndInvoke, parameters, this.ReturnType, null);
+ endInvoke.Flags = MethodFlags.Public | MethodFlags.HideBySig | MethodFlags.NewSlot | MethodFlags.Virtual;
+ endInvoke.CallingConvention = CallingConventionFlags.HasThis;
+ endInvoke.ImplFlags = MethodImplFlags.Runtime;
+ members.Add(endInvoke);
+ if (!this.IsGeneric)
+ {
+ TypeNodeList templPars = this.TemplateParameters;
+ for (int i = 0, m = templPars == null ? 0 : templPars.Count; i < m; i++)
+ {
+ //^ assert templPars != null;
+ TypeNode tpar = templPars[i];
+ if (tpar == null) continue;
+ members.Add(tpar);
+ }
+ }
+ }
+#endif
+ }
+#if !MinimalReader
+ public class FunctionType : DelegateNode
+ {
+ private FunctionType(Identifier name, TypeNode returnType, ParameterList parameters)
+ {
+ this.Flags = TypeFlags.Public | TypeFlags.Sealed;
+ this.Namespace = StandardIds.StructuralTypes;
+ this.Name = name;
+ this.returnType = returnType;
+ this.parameters = parameters;
+ }
+ public static FunctionType For(TypeNode returnType, ParameterList parameters, TypeNode referringType)
+ {
+ if (returnType == null || referringType == null) return null;
+ Module module = referringType.DeclaringModule;
+ if (module == null) return null;
+ TypeFlags visibility = returnType.Flags & TypeFlags.VisibilityMask;
+ StringBuilder name = new StringBuilder();
+ name.Append("Function_");
+ name.Append(returnType.Name.ToString());
+ int n = parameters == null ? 0 : parameters.Count;
+ if (parameters != null)
+ for (int i = 0; i < n; i++)
+ {
+ Parameter p = parameters[i];
+ if (p == null || p.Type == null) continue;
+ visibility = TypeNode.GetVisibilityIntersection(visibility, p.Type.Flags & TypeFlags.VisibilityMask);
+ name.Append('_');
+ name.Append(p.Type.Name.ToString());
+ }
+ FunctionType func = null;
+ int count = 0;
+ string fNameString = name.ToString();
+ Identifier fName = Identifier.For(fNameString);
+ TypeNode result = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, fName);
+ while (result != null)
+ {
+ //Mangled name is the same. But mangling is not unique (types are not qualified with assemblies), so check for equality.
+ func = result as FunctionType;
+ bool goodMatch = func != null && func.ReturnType == returnType;
+ if (goodMatch)
+ {
+ //^ assert func != null;
+ ParameterList fpars = func.Parameters;
+ int m = fpars == null ? 0 : fpars.Count;
+ goodMatch = n == m;
+ if (parameters != null && fpars != null)
+ for (int i = 0; i < n && goodMatch; i++)
+ {
+ Parameter p = parameters[i];
+ Parameter q = fpars[i];
+ goodMatch = p != null && q != null && p.Type == q.Type;
+ }
+ }
+ if (goodMatch) return func;
+ //Mangle some more
+ fName = Identifier.For(fNameString + (++count).ToString());
+ result = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, fName);
+ }
+ if (parameters != null)
+ {
+ ParameterList clonedParams = new ParameterList(n);
+ for (int i = 0; i < n; i++)
+ {
+ Parameter p = parameters[i];
+ if (p != null) p = (Parameter)p.Clone();
+ clonedParams.Add(p);
+ }
+ parameters = clonedParams;
+ }
+ func = new FunctionType(fName, returnType, parameters);
+ func.DeclaringModule = module;
+ switch (visibility)
+ {
+ case TypeFlags.NestedFamANDAssem:
+ case TypeFlags.NestedFamily:
+ case TypeFlags.NestedPrivate:
+ referringType.Members.Add(func);
+ func.DeclaringType = referringType;
+ func.Flags &= ~TypeFlags.VisibilityMask;
+ func.Flags |= TypeFlags.NestedPrivate;
+ break;
+ default:
+ module.Types.Add(func);
+ break;
+ }
+ module.StructurallyEquivalentType[func.Name.UniqueIdKey] = func;
+ func.ProvideMembers();
+ return func;
+ }
+ public override bool IsStructural
+ {
+ get { return true; }
+ }
+ protected TypeNodeList structuralElementTypes;
+ public override TypeNodeList StructuralElementTypes
+ {
+ get
+ {
+ TypeNodeList result = this.structuralElementTypes;
+ if (result != null) return result;
+ this.structuralElementTypes = result = new TypeNodeList();
+ result.Add(this.ReturnType);
+ ParameterList pars = this.Parameters;
+ for (int i = 0, n = pars == null ? 0 : pars.Count; i < n; i++)
+ {
+ Parameter par = pars[i];
+ if (par == null || par.Type == null) continue;
+ result.Add(par.Type);
+ }
+ return result;
+ }
+ }
+ public override bool IsStructurallyEquivalentTo(TypeNode type)
+ {
+ if (type == null) return false;
+ if (this == type) return true;
+ FunctionType t = type as FunctionType;
+ if (t == null) return false;
+ if (this.Template != null) return base.IsStructurallyEquivalentTo(t);
+ if (this.Flags != t.Flags) return false;
+ if (this.ReturnType == null || t.ReturnType == null) return false;
+ if (this.ReturnType != t.ReturnType && !this.ReturnType.IsStructurallyEquivalentTo(t.ReturnType)) return false;
+ if (this.Parameters == null) return t.Parameters == null;
+ if (t.Parameters == null) return false;
+ int n = this.Parameters.Count; if (n != t.Parameters.Count) return false;
+ for (int i = 0; i < n; i++)
+ {
+ Parameter p1 = this.Parameters[i];
+ Parameter p2 = t.Parameters[i];
+ if (p1 == null || p2 == null) return false;
+ if (p1.Type == null || p2.Type == null) return false;
+ if (p1.Type != p2.Type && !p1.Type.IsStructurallyEquivalentTo(p2.Type)) return false;
+ }
+ return true;
+ }
+ }
+#endif
+ public class EnumNode : TypeNode
+ {
+ internal readonly static EnumNode/*!*/ Dummy = new EnumNode();
+
+ public EnumNode()
+ : base(NodeType.EnumNode)
+ {
+ this.typeCode = ElementType.ValueType;
+ this.Flags |= TypeFlags.Sealed;
+ }
+ public EnumNode(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
+ : base(NodeType.EnumNode, provideNestedTypes, provideAttributes, provideMembers, handle)
+ {
+ this.typeCode = ElementType.ValueType;
+ this.Flags |= TypeFlags.Sealed;
+ }
+#if !MinimalReader
+ public EnumNode(Module declaringModule, TypeNode declaringType, AttributeList attributes, TypeFlags typeAttributes,
+ Identifier Namespace, Identifier name, InterfaceList interfaces, MemberList members)
+ : base(declaringModule, declaringType, attributes, typeAttributes, Namespace, name, interfaces, members, NodeType.EnumNode)
+ {
+ this.typeCode = ElementType.ValueType;
+ this.Flags |= TypeFlags.Sealed;
+ }
+#endif
+ public override bool IsUnmanaged
+ {
+ get
+ {
+ return true;
+ }
+ }
+ protected internal TypeNode underlyingType;
+ /// <summary>
+ /// The underlying integer type used to store values of this enumeration.
+ /// </summary>
+ public virtual TypeNode UnderlyingType
+ {
+ get
+ {
+ if (this.underlyingType == null)
+ {
+ if (this.template is EnumNode)
+ return this.underlyingType = ((EnumNode)this.template).UnderlyingType;
+ this.underlyingType = CoreSystemTypes.Int32;
+ MemberList members = this.Members;
+ for (int i = 0, n = members.Count; i < n; i++)
+ {
+ Member mem = members[i];
+ Field f = mem as Field;
+ if (f != null && (f.Flags & FieldFlags.Static) == 0)
+ return this.underlyingType = f.Type;
+ }
+ }
+ return this.underlyingType;
+ }
+ set
+ {
+ this.underlyingType = value;
+ MemberList members = this.Members;
+ for (int i = 0, n = members.Count; i < n; i++)
+ {
+ Member mem = members[i];
+ Field f = mem as Field;
+ if (f != null && (f.Flags & FieldFlags.Static) == 0)
+ {
+ f.Type = value;
+ return;
+ }
+ }
+ this.Members.Add(new Field(this, null, FieldFlags.Public | FieldFlags.SpecialName | FieldFlags.RTSpecialName, StandardIds.Value__, value, null));
+ }
+ }
+#if !MinimalReader
+ public TypeNode UnderlyingTypeExpression;
+#endif
+ }
+#if FxCop
+ public class InterfaceNode : TypeNode{
+#else
+ public class Interface : TypeNode
+ {
+#endif
+ protected TrivialHashtable jointMemberTable;
+ protected MemberList jointDefaultMembers;
+
+ internal static readonly Interface/*!*/ Dummy = new Interface();
+
+#if FxCop
+ public InterfaceNode()
+ : base(NodeType.Interface){
+ this.Flags = TypeFlags.Interface|TypeFlags.Abstract;
+ }
+ public InterfaceNode(InterfaceList baseInterfaces)
+ : base(NodeType.Interface){
+ this.Interfaces = baseInterfaces;
+ this.Flags = TypeFlags.Interface|TypeFlags.Abstract;
+ }
+ public InterfaceNode(InterfaceList baseInterfaces, NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
+ : base(NodeType.Interface, provideNestedTypes, provideAttributes, provideMembers, handle){
+ this.Interfaces = baseInterfaces;
+ }
+#else
+ public Interface()
+ : base(NodeType.Interface)
+ {
+ this.Flags = TypeFlags.Interface | TypeFlags.Abstract;
+ }
+ public Interface(InterfaceList baseInterfaces)
+ : base(NodeType.Interface)
+ {
+ this.Interfaces = baseInterfaces;
+ this.Flags = TypeFlags.Interface | TypeFlags.Abstract;
+ }
+ public Interface(InterfaceList baseInterfaces, NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
+ : base(NodeType.Interface, provideNestedTypes, provideAttributes, provideMembers, handle)
+ {
+ this.Interfaces = baseInterfaces;
+ }
+#endif
+#if !MinimalReader
+ public Interface(Module declaringModule, TypeNode declaringType, AttributeList attributes, TypeFlags flags,
+ Identifier Namespace, Identifier name, InterfaceList baseInterfaces, MemberList members)
+ : base(declaringModule, declaringType, attributes, flags, Namespace, name, baseInterfaces, members, NodeType.Interface)
+ {
+ this.Flags |= TypeFlags.Interface | TypeFlags.Abstract;
+ }
+ public override void GetAbstractMethods(MethodList/*!*/ result)
+ {
+ MemberList members = this.Members;
+ if (members == null) return;
+ for (int i = 0, n = members.Count; i < n; i++)
+ {
+ Method m = members[i] as Method;
+ if (m != null) result.Add(m);
+ }
+ }
+ public virtual MemberList GetAllDefaultMembers()
+ {
+ if (this.jointDefaultMembers == null)
+ {
+ this.jointDefaultMembers = new MemberList();
+ MemberList defs = this.DefaultMembers;
+ for (int i = 0, n = defs == null ? 0 : defs.Count; i < n; i++)
+ this.jointDefaultMembers.Add(defs[i]);
+ InterfaceList interfaces = this.Interfaces;
+ if (interfaces != null)
+ for (int j = 0, m = interfaces.Count; j < m; j++)
+ {
+ Interface iface = interfaces[j];
+ if (iface == null) continue;
+ defs = iface.GetAllDefaultMembers();
+ if (defs == null) continue;
+ for (int i = 0, n = defs.Count; i < n; i++)
+ this.jointDefaultMembers.Add(defs[i]);
+ }
+ }
+ return this.jointDefaultMembers;
+ }
+ public virtual MemberList GetAllMembersNamed(Identifier/*!*/ name)
+ {
+ lock (this)
+ {
+ TrivialHashtable memberTable = this.jointMemberTable;
+ if (memberTable == null) this.jointMemberTable = memberTable = new TrivialHashtable();
+ MemberList result = (MemberList)memberTable[name.UniqueIdKey];
+ if (result != null) return result;
+ memberTable[name.UniqueIdKey] = result = new MemberList();
+ MemberList members = this.GetMembersNamed(name);
+ for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++)
+ result.Add(members[i]);
+ InterfaceList interfaces = this.Interfaces;
+ for (int j = 0, m = interfaces == null ? 0 : interfaces.Count; j < m; j++)
+ {
+ Interface iface = interfaces[j];
+ if (iface == null) continue;
+ members = iface.GetAllMembersNamed(name);
+ if (members != null)
+ for (int i = 0, n = members.Count; i < n; i++)
+ result.Add(members[i]);
+ }
+ members = CoreSystemTypes.Object.GetMembersNamed(name);
+ for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++)
+ result.Add(members[i]);
+ return result;
+ }
+ }
+#endif
+ }
+ public class Struct : TypeNode
+ {
+ internal static readonly Struct/*!*/ Dummy = new Struct();
+
+ public Struct()
+ : base(NodeType.Struct)
+ {
+ this.typeCode = ElementType.ValueType;
+ this.Flags = TypeFlags.Sealed;
+ }
+ public Struct(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
+ : base(NodeType.Struct, provideNestedTypes, provideAttributes, provideMembers, handle)
+ {
+ this.typeCode = ElementType.ValueType;
+ }
+#if !MinimalReader
+ public Struct(Module declaringModule, TypeNode declaringType, AttributeList attributes, TypeFlags flags,
+ Identifier Namespace, Identifier name, InterfaceList interfaces, MemberList members)
+ : base(declaringModule, declaringType, attributes, flags, Namespace, name, interfaces, members, NodeType.Struct)
+ {
+ this.Interfaces = interfaces;
+ this.typeCode = ElementType.ValueType;
+ this.Flags |= TypeFlags.Sealed;
+ }
+ protected bool cachedUnmanaged;
+ protected bool cachedUnmanagedIsValid;
+ /// <summary>True if the type is a value type containing only fields of unmanaged types.</summary>
+ public override bool IsUnmanaged
+ {
+ get
+ {
+ if (this.cachedUnmanagedIsValid) return this.cachedUnmanaged;
+ this.cachedUnmanagedIsValid = true; //protect against cycles
+ this.cachedUnmanaged = true; //Self references should not influence the answer
+ if (this.IsPrimitive) return this.cachedUnmanaged = true;
+ MemberList members = this.Members;
+ bool isUnmanaged = true;
+ for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++)
+ {
+ Field f = members[i] as Field;
+ if (f == null || f.Type == null || f.IsStatic) continue;
+ if (!f.Type.IsUnmanaged) { isUnmanaged = false; break; }
+ }
+ return this.cachedUnmanaged = isUnmanaged;
+ }
+ }
+#endif
+ }
+ public interface ITypeParameter
+ {
+ Member DeclaringMember { get; set; }
+ /// <summary>
+ /// Zero based index into a parameter list containing this parameter.
+ /// </summary>
+ int ParameterListIndex { get; set; }
+ TypeParameterFlags TypeParameterFlags { get; set; }
+ bool IsUnmanaged { get; }
+#if !MinimalReader
+ Identifier Name { get; }
+ Module DeclaringModule { get; }
+ TypeNode DeclaringType { get; }
+ SourceContext SourceContext { get; }
+ int UniqueKey { get; }
+ TypeFlags Flags { get; }
+#endif
+ }
+ public class TypeParameter : Interface, ITypeParameter
+ {
+
+ public TypeParameter()
+ : base()
+ {
+ this.NodeType = NodeType.TypeParameter;
+ this.Flags = TypeFlags.Interface | TypeFlags.NestedPublic | TypeFlags.Abstract;
+ this.Namespace = StandardIds.TypeParameter;
+ }
+ public TypeParameter(InterfaceList baseInterfaces, NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
+ : base(baseInterfaces, provideNestedTypes, provideAttributes, provideMembers, handle)
+ {
+ this.NodeType = NodeType.TypeParameter;
+ this.Flags = TypeFlags.Interface | TypeFlags.NestedPublic | TypeFlags.Abstract;
+ this.Namespace = StandardIds.TypeParameter;
+ }
+
+ public Member DeclaringMember
+ {
+ get { return this.declaringMember; }
+ set { this.declaringMember = value; }
+ }
+ private Member declaringMember;
+#if !NoReflection && WHIDBEY
+ public override Type GetRuntimeType()
+ {
+ TypeNode t = this.DeclaringMember as TypeNode;
+ if (t == null) return null;
+ Type rt = t.GetRuntimeType();
+ if (rt == null) return null;
+ System.Type[] typeParameters = rt.GetGenericArguments();
+ if (this.ParameterListIndex >= typeParameters.Length) return null;
+ return typeParameters[this.ParameterListIndex];
+ }
+#endif
+ /// <summary>
+ /// Zero based index into a parameter list containing this parameter.
+ /// </summary>
+ public int ParameterListIndex
+ {
+ get { return this.parameterListIndex; }
+ set { this.parameterListIndex = value; }
+ }
+ private int parameterListIndex;
+#if ExtendedRuntime
+ private bool typeParameterFlagsIsValid = false;
+#endif
+ public TypeParameterFlags TypeParameterFlags
+ {
+ get
+ {
+#if ExtendedRuntime
+ if (!typeParameterFlagsIsValid) {
+ // check if we have the corresponding attribute
+ for (int i=0; i < (this.Attributes == null?0:this.Attributes.Count); i++) {
+ if (this.Attributes[i].Type == SystemTypes.TemplateParameterFlagsAttribute) {
+ Literal lit = this.Attributes[i].Expressions[0] as Literal;
+ if (lit != null && lit.Value is int) {
+ this.typeParameterFlags = (TypeParameterFlags)((int)lit.Value);
+ }
+ break;
+ }
+ }
+ this.typeParameterFlagsIsValid = true;
+ }
+#endif
+ return this.typeParameterFlags;
+ }
+ set
+ {
+ this.typeParameterFlags = value;
+#if ExtendedRuntime
+ this.typeParameterFlagsIsValid = true;
+#endif
+ }
+ }
+ private TypeParameterFlags typeParameterFlags;
+ public override bool IsStructural
+ {
+ get { return true; }
+ }
+ /// <summary>True if the type serves as a parameter to a type template.</summary>
+ public override bool IsTemplateParameter
+ {
+ get
+ {
+ return true;
+ }
+ }
+ public override bool IsValueType
+ {
+ get
+ {
+ return ((this.TypeParameterFlags & TypeParameterFlags.ValueTypeConstraint) == TypeParameterFlags.ValueTypeConstraint);
+ }
+ }
+#if ExtendedRuntime
+ public override bool IsReferenceType {
+ get {
+ return ((this.TypeParameterFlags & TypeParameterFlags.ReferenceTypeConstraint) == TypeParameterFlags.ReferenceTypeConstraint);
+ }
+ }
+ private bool isUnmanagedIsValid = false;
+ private bool isUnmanaged = false;
+ public override bool IsUnmanaged{
+ get{
+ if (!isUnmanagedIsValid && SystemTypes.UnmanagedStructTemplateParameterAttribute != null){
+ // check if we have the corresponding attribute
+ for (int i=0; i < (this.Attributes == null?0:this.Attributes.Count); i++){
+ AttributeNode attr = this.Attributes[i];
+ if (attr == null) continue;
+ if (attr.Type == SystemTypes.UnmanagedStructTemplateParameterAttribute){
+ isUnmanaged = true;
+ break;
+ }
+ }
+ isUnmanagedIsValid = true;
+ }
+ return isUnmanaged;
+ }
+ }
+ public void SetIsUnmanaged(){
+ this.isUnmanaged = true;
+ this.isUnmanagedIsValid = true;
+ }
+#endif
+#if !NoXml
+ public override XmlNode Documentation
+ {
+ get
+ {
+ if (this.documentation == null && this.declaringMember != null && this.Name != null)
+ {
+ XmlNode parentDoc = this.declaringMember.Documentation;
+ if (parentDoc != null && parentDoc.HasChildNodes)
+ {
+ string myName = this.Name.Name;
+ foreach (XmlNode child in parentDoc.ChildNodes)
+ {
+ if (child.Name == "typeparam" && child.Attributes != null)
+ {
+ foreach (XmlAttribute attr in child.Attributes)
+ {
+ if (attr != null && attr.Name == "name" && attr.Value == myName)
+ return this.documentation = child;
+ }
+ }
+ }
+ }
+ }
+ return this.documentation;
+ }
+ set
+ {
+ this.documentation = value;
+ }
+ }
+ public override string HelpText
+ {
+ get
+ {
+ if (this.helpText == null)
+ {
+ XmlNode doc = this.Documentation;
+ if (doc != null) this.helpText = doc.InnerText;
+ }
+ return this.helpText;
+ }
+ set
+ {
+ this.helpText = value;
+ }
+ }
+#endif
+ protected internal TypeNodeList structuralElementTypes;
+ public override TypeNodeList StructuralElementTypes
+ {
+ get
+ {
+ TypeNodeList result = this.structuralElementTypes;
+ if (result != null) return result;
+ this.structuralElementTypes = result = new TypeNodeList();
+ if (this.BaseType != null) result.Add(this.BaseType);
+ InterfaceList interfaces = this.Interfaces;
+ for (int i = 0, n = interfaces == null ? 0 : interfaces.Count; i < n; i++)
+ {
+ Interface iface = interfaces[i];
+ if (iface == null) continue;
+ result.Add(iface);
+ }
+ return result;
+ }
+ }
+#if !NoXml
+ internal override void AppendDocumentIdMangledName(StringBuilder/*!*/ sb, TypeNodeList methodTypeParameters, TypeNodeList typeParameters)
+ {
+ if (TargetPlatform.GenericTypeNamesMangleChar != 0)
+ {
+ int n = methodTypeParameters == null ? 0 : methodTypeParameters.Count;
+ for (int i = 0; i < n; i++)
+ {
+ //^ assert methodTypeParameters != null;
+ TypeNode mpar = methodTypeParameters[i];
+ if (mpar != this) continue;
+ sb.Append(TargetPlatform.GenericTypeNamesMangleChar);
+ sb.Append(TargetPlatform.GenericTypeNamesMangleChar);
+ sb.Append(i);
+ return;
+ }
+ n = typeParameters == null ? 0 : typeParameters.Count;
+ for (int i = 0; i < n; i++)
+ {
+ TypeNode tpar = typeParameters[i];
+ if (tpar != this) continue;
+ sb.Append(TargetPlatform.GenericTypeNamesMangleChar);
+ sb.Append(i);
+ return;
+ }
+ sb.Append("not found:");
+ }
+ sb.Append(this.FullName);
+ }
+#endif
+ public override string GetFullUnmangledNameWithoutTypeParameters()
+ {
+ return this.GetUnmangledNameWithoutTypeParameters();
+ }
+ public override string GetFullUnmangledNameWithTypeParameters()
+ {
+ return this.GetUnmangledNameWithTypeParameters();
+ }
+ public override bool IsStructurallyEquivalentTo(TypeNode type)
+ {
+ if (null == (object)type) return false;
+ if (this == type) return true;
+ ITypeParameter itype = type as ITypeParameter;
+ if (null == (object)itype) return false;
+ if (this.Name != null && type.Name != null && this.Name.UniqueIdKey != type.Name.UniqueIdKey)
+ {
+ if (this.DeclaringMember == itype.DeclaringMember) return false;
+ }
+ TypeNode bType = this.BaseType;
+ TypeNode tbType = type.BaseType;
+ if (null == (object)bType) bType = CoreSystemTypes.Object;
+ if (null == (object)tbType) tbType = CoreSystemTypes.Object;
+ if (bType != tbType /*&& !bType.IsStructurallyEquivalentTo(tbType)*/) return false;
+ if (this.Interfaces == null) return type.Interfaces == null || type.Interfaces.Count == 0;
+ if (type.Interfaces == null) return this.Interfaces.Count == 0;
+ int n = this.Interfaces.Count; if (n != type.Interfaces.Count) return false;
+ for (int i = 0; i < n; i++)
+ {
+ Interface i1 = this.Interfaces[i];
+ Interface i2 = type.Interfaces[i];
+ if (null == (object)i1 || null == (object)i2) return false;
+ if (i1 != i2 /*&& !i1.IsStructurallyEquivalentTo(i2)*/) return false;
+ }
+ return true;
+ }
+#if !MinimalReader
+ Module ITypeParameter.DeclaringModule { get { return this.DeclaringModule; } }
+ TypeFlags ITypeParameter.Flags { get { return this.Flags; } }
+ SourceContext ITypeParameter.SourceContext { get { return this.SourceContext; } }
+#endif
+#if FxCop
+ internal override void GetName(TypeFormat options, StringBuilder name)
+ {
+ if (options.TypeName == TypeNameFormat.FullyQualified)
+ {
+ TypeFormat typeFormat = options.Clone();
+ typeFormat.TypeName = TypeNameFormat.Short;
+ base.GetName(typeFormat, name);
+ return;
+ }
+ base.GetName(options, name);
+ }
+#endif
+ }
+ public class MethodTypeParameter : TypeParameter
+ {
+ public MethodTypeParameter()
+ : base()
+ {
+ this.NodeType = NodeType.TypeParameter;
+ this.Flags = TypeFlags.Interface | TypeFlags.NestedPublic | TypeFlags.Abstract;
+ this.Namespace = StandardIds.TypeParameter;
+ }
+#if !MinimalReader
+ public MethodTypeParameter(InterfaceList baseInterfaces, NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
+ : base(baseInterfaces, provideNestedTypes, provideAttributes, provideMembers, handle)
+ {
+ this.NodeType = NodeType.TypeParameter;
+ this.Flags = TypeFlags.Interface | TypeFlags.NestedPublic | TypeFlags.Abstract;
+ this.Namespace = StandardIds.TypeParameter;
+ }
+#endif
+#if !NoReflection
+#if WHIDBEY
+ public override Type GetRuntimeType()
+ {
+ Method m = this.DeclaringMember as Method;
+ if (m == null) return null;
+ System.Reflection.MethodInfo mi = m.GetMethodInfo();
+ if (mi == null) return null;
+ System.Type[] typeParameters = mi.GetGenericArguments();
+ if (this.ParameterListIndex >= typeParameters.Length) return null;
+ return typeParameters[this.ParameterListIndex];
+ }
+#endif
+#endif
+ public override bool IsStructurallyEquivalentTo(TypeNode type)
+ {
+ if (object.ReferenceEquals(this, type)) return true;
+ ITypeParameter tp = type as ITypeParameter;
+ if (tp == null) return false;
+ if (this.ParameterListIndex == tp.ParameterListIndex && this.DeclaringMember == tp.DeclaringMember) return true;
+ return base.IsStructurallyEquivalentTo(type as MethodTypeParameter);
+ }
+ }
+ public class ClassParameter : Class, ITypeParameter
+ {
+ protected TrivialHashtable jointMemberTable;
+
+ public ClassParameter()
+ : base()
+ {
+ this.NodeType = NodeType.ClassParameter;
+ this.baseClass = CoreSystemTypes.Object;
+ this.Flags = TypeFlags.NestedPublic | TypeFlags.Abstract;
+ this.Namespace = StandardIds.TypeParameter;
+ }
+ public ClassParameter(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
+ : base(provideNestedTypes, provideAttributes, provideMembers, handle)
+ {
+ this.NodeType = NodeType.ClassParameter;
+ this.baseClass = CoreSystemTypes.Object;
+ this.Flags = TypeFlags.NestedPrivate | TypeFlags.Abstract | TypeFlags.SpecialName;
+ this.Namespace = StandardIds.TypeParameter;
+ }
+
+ public Member DeclaringMember
+ {
+ get { return this.declaringMember; }
+ set { this.declaringMember = value; }
+ }
+ private Member declaringMember;
+#if !MinimalReader
+ public virtual MemberList GetAllMembersNamed(Identifier/*!*/ name)
+ {
+ lock (this)
+ {
+ TrivialHashtable memberTable = this.jointMemberTable;
+ if (memberTable == null) this.jointMemberTable = memberTable = new TrivialHashtable();
+ MemberList result = (MemberList)memberTable[name.UniqueIdKey];
+ if (result != null) return result;
+ memberTable[name.UniqueIdKey] = result = new MemberList();
+ TypeNode t = this;
+ while (t != null)
+ {
+ MemberList members = t.GetMembersNamed(name);
+ if (members != null)
+ for (int i = 0, n = members.Count; i < n; i++)
+ result.Add(members[i]);
+ t = t.BaseType;
+ }
+ InterfaceList interfaces = this.Interfaces;
+ if (interfaces != null)
+ for (int j = 0, m = interfaces.Count; j < m; j++)
+ {
+ Interface iface = interfaces[j];
+ if (iface == null) continue;
+ members = iface.GetAllMembersNamed(name);
+ if (members != null)
+ for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++)
+ result.Add(members[i]);
+ }
+ members = CoreSystemTypes.Object.GetMembersNamed(name);
+ if (members != null)
+ for (int i = 0, n = members.Count; i < n; i++)
+ result.Add(members[i]);
+ return result;
+ }
+ }
+#endif
+
+#if !NoReflection && WHIDBEY
+ public override Type GetRuntimeType()
+ {
+ TypeNode t = this.DeclaringMember as TypeNode;
+ if (t == null) return null;
+ Type rt = t.GetRuntimeType();
+ if (rt == null) return null;
+ System.Type[] typeParameters = rt.GetGenericArguments();
+ if (this.ParameterListIndex >= typeParameters.Length) return null;
+ return typeParameters[this.ParameterListIndex];
+ }
+#endif
+
+ /// <summary>
+ /// Zero based index into a parameter list containing this parameter.
+ /// </summary>
+ public int ParameterListIndex
+ {
+ get { return this.parameterListIndex; }
+ set { this.parameterListIndex = value; }
+ }
+ private int parameterListIndex;
+ public TypeParameterFlags TypeParameterFlags
+ {
+ get { return this.typeParameterFlags; }
+ set { this.typeParameterFlags = value; }
+ }
+ private TypeParameterFlags typeParameterFlags;
+ public override bool IsValueType
+ {
+ get
+ {
+ return ((this.typeParameterFlags & TypeParameterFlags.SpecialConstraintMask) == TypeParameterFlags.ValueTypeConstraint);
+ }
+ }
+ public override bool IsStructural
+ {
+ get { return true; }
+ }
+ /// <summary>True if the type serves as a parameter to a type template.</summary>
+ public override bool IsTemplateParameter
+ {
+ get
+ {
+ return true;
+ }
+ }
+#if ExtendedRuntime
+ public override bool IsReferenceType {
+ get {
+ return ((this.TypeParameterFlags & TypeParameterFlags.ReferenceTypeConstraint) == TypeParameterFlags.ReferenceTypeConstraint)
+ || (this.baseClass != null && this.baseClass.IsReferenceType);
+ }
+ }
+ private bool isUnmanagedIsValid = false;
+ private bool isUnmanaged = false;
+ public override bool IsUnmanaged{
+ get{
+ if (!isUnmanagedIsValid && SystemTypes.UnmanagedStructTemplateParameterAttribute != null){
+ // check if we have the corresponding attribute
+ for (int i=0; i < (this.Attributes == null?0:this.Attributes.Count); i++){
+ if (this.Attributes[i].Type == SystemTypes.UnmanagedStructTemplateParameterAttribute){
+ isUnmanaged = true;
+ break;
+ }
+ }
+ isUnmanagedIsValid = true;
+ }
+ return isUnmanaged;
+ }
+ }
+ public void SetIsUnmanaged(){
+ this.isUnmanaged = true;
+ this.isUnmanagedIsValid = true;
+ }
+#endif
+#if !NoXml
+ public override XmlNode Documentation
+ {
+ get
+ {
+ if (this.documentation == null && this.declaringMember != null && this.Name != null)
+ {
+ XmlNode parentDoc = this.declaringMember.Documentation;
+ if (parentDoc != null && parentDoc.HasChildNodes)
+ {
+ string myName = this.Name.Name;
+ foreach (XmlNode child in parentDoc.ChildNodes)
+ {
+ if (child.Name == "typeparam" && child.Attributes != null)
+ {
+ foreach (XmlAttribute attr in child.Attributes)
+ {
+ if (attr != null && attr.Name == "name" && attr.Value == myName)
+ return this.documentation = child;
+ }
+ }
+ }
+ }
+ }
+ return this.documentation;
+ }
+ set
+ {
+ this.documentation = value;
+ }
+ }
+ public override string HelpText
+ {
+ get
+ {
+ if (this.helpText == null)
+ {
+ XmlNode doc = this.Documentation;
+ if (doc != null) this.helpText = doc.InnerText;
+ }
+ return this.helpText;
+ }
+ set
+ {
+ this.helpText = value;
+ }
+ }
+#endif
+ protected internal TypeNodeList structuralElementTypes;
+ public override TypeNodeList StructuralElementTypes
+ {
+ get
+ {
+ TypeNodeList result = this.structuralElementTypes;
+ if (result != null) return result;
+ this.structuralElementTypes = result = new TypeNodeList();
+ if (this.BaseType != null) result.Add(this.BaseType);
+ InterfaceList interfaces = this.Interfaces;
+ for (int i = 0, n = interfaces == null ? 0 : interfaces.Count; i < n; i++)
+ {
+ Interface iface = interfaces[i];
+ if (iface == null) continue;
+ result.Add(iface);
+ }
+ return result;
+ }
+ }
+#if !NoXml
+ internal override void AppendDocumentIdMangledName(StringBuilder/*!*/ sb, TypeNodeList methodTypeParameters, TypeNodeList typeParameters)
+ {
+ if (TargetPlatform.GenericTypeNamesMangleChar != 0)
+ {
+ int n = methodTypeParameters == null ? 0 : methodTypeParameters.Count;
+ for (int i = 0; i < n; i++)
+ {
+ //^ assert methodTypeParameters != null;
+ TypeNode mpar = methodTypeParameters[i];
+ if (mpar != this) continue;
+ sb.Append(TargetPlatform.GenericTypeNamesMangleChar);
+ sb.Append(TargetPlatform.GenericTypeNamesMangleChar);
+ sb.Append(i);
+ return;
+ }
+ n = typeParameters == null ? 0 : typeParameters.Count;
+ for (int i = 0; i < n; i++)
+ {
+ TypeNode tpar = typeParameters[i];
+ if (tpar != this) continue;
+ sb.Append(TargetPlatform.GenericTypeNamesMangleChar);
+ sb.Append(i);
+ return;
+ }
+ sb.Append("not found:");
+ }
+ sb.Append(this.FullName);
+ }
+#endif
+ public override string GetFullUnmangledNameWithoutTypeParameters()
+ {
+ return this.GetUnmangledNameWithoutTypeParameters();
+ }
+ public override string GetFullUnmangledNameWithTypeParameters()
+ {
+ return this.GetUnmangledNameWithTypeParameters();
+ }
+ public override bool IsStructurallyEquivalentTo(TypeNode type)
+ {
+ if (null == (object)type) return false;
+ if (this == type) return true;
+ ITypeParameter itype = type as ITypeParameter;
+ if (null == (object)itype) return false;
+ if (this.Name != null && type.Name != null && this.Name.UniqueIdKey != type.Name.UniqueIdKey)
+ {
+ if (this.DeclaringMember == itype.DeclaringMember) return false;
+ }
+ TypeNode bType = this.BaseType;
+ TypeNode tbType = type.BaseType;
+ if (null == (object)bType) bType = CoreSystemTypes.Object;
+ if (null == (object)tbType) tbType = CoreSystemTypes.Object;
+ if (bType != tbType /*&& !bType.IsStructurallyEquivalentTo(tbType)*/) return false;
+ if (this.Interfaces == null) return type.Interfaces == null || type.Interfaces.Count == 0;
+ if (type.Interfaces == null) return this.Interfaces.Count == 0;
+ int n = this.Interfaces.Count; if (n != type.Interfaces.Count) return false;
+ for (int i = 0; i < n; i++)
+ {
+ Interface i1 = this.Interfaces[i];
+ Interface i2 = type.Interfaces[i];
+ if (null == (object)i1 || null == (object)i2) return false;
+ if (i1 != i2 /*&& !i1.IsStructurallyEquivalentTo(i2)*/) return false;
+ }
+ return true;
+ }
+#if !MinimalReader
+ SourceContext ITypeParameter.SourceContext { get { return this.SourceContext; } }
+ Module ITypeParameter.DeclaringModule { get { return this.DeclaringModule; } }
+ TypeFlags ITypeParameter.Flags { get { return this.Flags; } }
+#endif
+#if FxCop
+ internal override void GetName(TypeFormat options, StringBuilder name)
+ {
+ if (options.TypeName == TypeNameFormat.FullyQualified)
+ {
+ TypeFormat typeFormat = options.Clone();
+ typeFormat.TypeName = TypeNameFormat.Short;
+ base.GetName(typeFormat, name);
+ return;
+ }
+ base.GetName(options, name);
+ }
+#endif
+ }
+ public class MethodClassParameter : ClassParameter
+ {
+ public MethodClassParameter()
+ : base()
+ {
+ this.NodeType = NodeType.ClassParameter;
+ this.baseClass = CoreSystemTypes.Object;
+ this.Flags = TypeFlags.NestedPublic | TypeFlags.Abstract;
+ this.Namespace = StandardIds.TypeParameter;
+ }
+#if !NoReflection && WHIDBEY
+ public override Type GetRuntimeType()
+ {
+ Method m = this.DeclaringMember as Method;
+ if (m == null) return null;
+ System.Reflection.MethodInfo mi = m.GetMethodInfo();
+ if (mi == null) return null;
+ System.Type[] typeParameters = mi.GetGenericArguments();
+ if (this.ParameterListIndex >= typeParameters.Length) return null;
+ return typeParameters[this.ParameterListIndex];
+ }
+#endif
+#if !MinimalReader
+ public override bool IsStructurallyEquivalentTo(TypeNode type)
+ {
+ if (object.ReferenceEquals(this, type)) return true;
+ ITypeParameter tp = type as ITypeParameter;
+ if (tp == null) return false;
+ if (this.ParameterListIndex == tp.ParameterListIndex /* && this.DeclaringMember == tp.DeclaringMember*/) return true;
+ return base.IsStructurallyEquivalentTo(type as MethodClassParameter);
+ }
+#endif
+ }
+ public class ArrayType : TypeNode
+ {
+ private TypeNode/*!*/ elementType;
+ private int rank;
+ private int[] lowerBounds;
+ private int[] sizes;
+ internal ArrayType()
+ : base(NodeType.ArrayType)
+ {
+ }
+ internal ArrayType(TypeNode/*!*/ elementType, int rank)
+ : this(elementType, rank, new int[0], new int[0])
+ {
+ if (rank == 1)
+ this.typeCode = Metadata.ElementType.SzArray;
+ else
+ this.typeCode = Metadata.ElementType.Array;
+ }
+ internal ArrayType(TypeNode/*!*/ elementType, int rank, int[] sizes)
+ : this(elementType, rank, sizes, new int[0])
+ {
+ }
+ internal ArrayType(TypeNode/*!*/ elementType, int rank, int[] sizes, int[] lowerBounds)
+ : base(null, null, null, elementType.Flags, null, null, null, null, NodeType.ArrayType)
+ {
+ Debug.Assert(elementType != null);
+ this.rank = rank;
+ this.elementType = elementType;
+ this.DeclaringModule = elementType.DeclaringModule;
+ this.lowerBounds = lowerBounds;
+ this.sizes = sizes;
+ if (rank == 1)
+ this.typeCode = Metadata.ElementType.SzArray;
+ else
+ this.typeCode = Metadata.ElementType.Array;
+ if (elementType == null || elementType.Name == null) return;
+ StringBuilder name = new StringBuilder(this.ElementType.Name.ToString());
+#if FxCop
+ GetNameSuffix(name, false);
+#else
+ name.Append('[');
+ int k = this.Sizes == null ? 0 : this.Sizes.Length;
+ int m = this.LowerBounds == null ? 0 : this.LowerBounds.Length;
+ for (int i = 0, n = this.Rank; i < n; i++)
+ {
+ if (i < k && this.Sizes[i] != 0)
+ {
+ if (i < m && this.LowerBounds[i] != 0)
+ {
+ name.Append(this.LowerBounds[i]);
+ name.Append(':');
+ }
+ name.Append(this.Sizes[i]);
+ }
+ if (i < n - 1)
+ name.Append(',');
+ }
+ name.Append(']');
+#endif
+ this.Name = Identifier.For(name.ToString());
+ this.Namespace = elementType.Namespace;
+ }
+ public TypeNode/*!*/ ElementType
+ {
+ get { return this.elementType; }
+ set { this.elementType = value; }
+ }
+ /// <summary>The interfaces implemented by this class or struct, or the extended by this interface.</summary>
+ public override InterfaceList Interfaces
+ {
+ get
+ {
+ if (this.interfaces == null)
+ {
+ InterfaceList interfaces = new InterfaceList(SystemTypes.ICloneable, SystemTypes.IList, SystemTypes.ICollection, SystemTypes.IEnumerable);
+ if (this.Rank == 1)
+ {
+ if (SystemTypes.GenericIEnumerable != null && SystemTypes.GenericIEnumerable.DeclaringModule == CoreSystemTypes.SystemAssembly)
+ {
+ interfaces.Add((Interface)SystemTypes.GenericIEnumerable.GetTemplateInstance(this, elementType));
+ if (SystemTypes.GenericICollection != null)
+ interfaces.Add((Interface)SystemTypes.GenericICollection.GetTemplateInstance(this, elementType));
+ if (SystemTypes.GenericIList != null)
+ interfaces.Add((Interface)SystemTypes.GenericIList.GetTemplateInstance(this, elementType));
+ }
+ }
+ this.interfaces = interfaces;
+ }
+ return this.interfaces;
+ }
+ set { this.interfaces = value; }
+ }
+ public int Rank
+ {
+ get { return this.rank; }
+ set { this.rank = value; }
+ }
+ public int[] LowerBounds
+ {
+ get { return this.lowerBounds; }
+ set { this.lowerBounds = value; }
+ }
+ public int[] Sizes
+ {
+ get { return this.sizes; }
+ set { this.sizes = value; }
+ }
+ public bool IsSzArray()
+ {
+ return this.typeCode == Metadata.ElementType.SzArray;
+ }
+ private MemberList ctorList = null;
+ private MemberList getterList = null;
+ private MemberList setterList = null;
+ private MemberList addressList = null;
+ public override MemberList Members
+ {
+ get
+ {
+ if (this.members == null || this.membersBeingPopulated)
+ {
+ lock (this)
+ {
+ if (this.members == null)
+ {
+ this.membersBeingPopulated = true;
+ MemberList members = this.members = new MemberList(5);
+ members.Add(this.Constructor);
+ //^ assume this.ctorList != null && this.ctorList.Length > 1;
+ members.Add(this.ctorList[1]);
+ members.Add(this.Getter);
+ members.Add(this.Setter);
+ members.Add(this.Address);
+ this.membersBeingPopulated = false;
+ }
+ }
+ }
+ return this.members;
+ }
+ set
+ {
+ this.members = value;
+ }
+ }
+ public override string/*!*/ FullName
+ {
+ get
+ {
+ if (this.ElementType != null && this.ElementType.DeclaringType != null)
+ return this.ElementType.DeclaringType.FullName + "+" + (this.Name == null ? "" : this.Name.ToString());
+ else if (this.Namespace != null && this.Namespace.UniqueIdKey != Identifier.Empty.UniqueIdKey)
+ return this.Namespace.ToString() + "." + (this.Name == null ? "" : this.Name.ToString());
+ else if (this.Name != null)
+ return this.Name.ToString();
+ else
+ return "";
+ }
+ }
+#if !NoXml
+ internal override void AppendDocumentIdMangledName(StringBuilder/*!*/ sb, TypeNodeList methodTypeParameters, TypeNodeList typeParameters)
+ {
+ if (this.ElementType == null) return;
+ this.ElementType.AppendDocumentIdMangledName(sb, methodTypeParameters, typeParameters);
+ sb.Append('[');
+ int k = this.Sizes == null ? 0 : this.Sizes.Length;
+ int m = this.LowerBounds == null ? 0 : this.LowerBounds.Length;
+ for (int i = 0, n = this.Rank; i < n; i++)
+ {
+ if (i < k && this.Sizes[i] != 0)
+ {
+ if (i < m && this.LowerBounds[i] != 0)
+ {
+ sb.Append(this.LowerBounds[i]);
+ sb.Append(':');
+ }
+ sb.Append(this.Sizes[i]);
+ }
+ if (i < n - 1)
+ sb.Append(',');
+ }
+ sb.Append(']');
+ }
+#endif
+ public virtual void SetLowerBoundToUnknown()
+ {
+ Debug.Assert(this.Rank == 1);
+ this.typeCode = Metadata.ElementType.Array;
+ }
+ public virtual int GetLowerBound(int dimension)
+ {
+ if (this.LowerBounds == null || this.LowerBounds.Length <= dimension) return 0;
+ return this.LowerBounds[dimension];
+ }
+ public virtual int GetSize(int dimension)
+ {
+ if (this.Sizes == null || this.Sizes.Length <= dimension) return 0;
+ return this.Sizes[dimension];
+ }
+ public override MemberList/*!*/ GetMembersNamed(Identifier name)
+ {
+ if (name == null) return new MemberList(0);
+ if (name.UniqueIdKey == StandardIds.Get.UniqueIdKey)
+ {
+ if (this.getterList == null)
+ {
+ Method getter = this.Getter;
+ if (getter != null) getter = null;
+ //^ assume this.getterList != null;
+ }
+ return this.getterList;
+ }
+ else if (name.UniqueIdKey == StandardIds.Set.UniqueIdKey)
+ {
+ if (this.setterList == null)
+ {
+ Method setter = this.Setter;
+ if (setter != null) setter = null;
+ //^ assume this.setterList != null;
+ }
+ return this.setterList;
+ }
+ else if (name.UniqueIdKey == StandardIds.Ctor.UniqueIdKey)
+ {
+ if (this.ctorList == null)
+ {
+ Method ctor = this.Constructor;
+ if (ctor != null) ctor = null;
+ //^ assume this.ctorList != null;
+ }
+ return this.ctorList;
+ }
+ else if (name.UniqueIdKey == StandardIds.Address.UniqueIdKey)
+ {
+ if (this.addressList == null)
+ {
+ Method addr = this.Address;
+ if (addr != null) addr = null;
+ //^ assume this.addressList != null;
+ }
+ return this.addressList;
+ }
+ else
+ return new MemberList(0);
+ }
+#if !NoReflection
+ public override Type GetRuntimeType()
+ {
+ if (this.runtimeType == null)
+ {
+ if (this.ElementType == null) return null;
+ Type eType = this.ElementType.GetRuntimeType();
+ if (eType == null) return null;
+#if WHIDBEY
+ if (this.IsSzArray())
+ this.runtimeType = eType.MakeArrayType();
+ else
+ this.runtimeType = eType.MakeArrayType(this.Rank);
+#else
+ StringBuilder sb = new StringBuilder(eType.FullName);
+ sb.Append('[');
+ for (int i = 1, n = this.Rank; i < n; i++) sb.Append(',');
+ sb.Append(']');
+ if (eType.Assembly != null)
+ this.runtimeType = eType.Assembly.GetType(sb.ToString(), false);
+ else if (eType.Module != null)
+ this.runtimeType = eType.Module.GetType(sb.ToString(), false);
+#endif
+ }
+ return this.runtimeType;
+ }
+#endif
+ public Method Constructor
+ {
+ get
+ {
+ if (this.ctorList == null)
+ {
+ lock (this)
+ {
+ if (this.ctorList == null)
+ {
+ InstanceInitializer ctor = new InstanceInitializer();
+ ctor.DeclaringType = this;
+ ctor.Flags |= MethodFlags.Public;
+ int n = this.Rank;
+ ctor.Parameters = new ParameterList(n);
+ for (int i = 0; i < n; i++)
+ {
+ Parameter par = new Parameter();
+ par.DeclaringMethod = ctor;
+ par.Type = CoreSystemTypes.Int32;
+ ctor.Parameters.Add(par);
+ }
+ this.ctorList = new MemberList(2);
+ this.ctorList.Add(ctor);
+ ctor = new InstanceInitializer();
+ ctor.DeclaringType = this;
+ ctor.Flags |= MethodFlags.Public;
+ ctor.Parameters = new ParameterList(n = n * 2);
+ for (int i = 0; i < n; i++)
+ {
+ Parameter par = new Parameter();
+ par.Type = CoreSystemTypes.Int32;
+ par.DeclaringMethod = ctor;
+ ctor.Parameters.Add(par);
+ }
+ this.ctorList.Add(ctor);
+ }
+ }
+ }
+ return (Method)this.ctorList[0];
+ }
+ }
+ public Method Getter
+ {
+ get
+ {
+ if (this.getterList == null)
+ {
+ lock (this)
+ {
+ if (this.getterList == null)
+ {
+ Method getter = new Method();
+ getter.Name = StandardIds.Get;
+ getter.DeclaringType = this;
+ getter.CallingConvention = CallingConventionFlags.HasThis;
+ getter.Flags = MethodFlags.Public;
+ getter.Parameters = new ParameterList();
+ for (int i = 0, n = this.Rank; i < n; i++)
+ {
+ Parameter par = new Parameter();
+ par.Type = CoreSystemTypes.Int32;
+ par.DeclaringMethod = getter;
+ getter.Parameters.Add(par);
+ }
+ getter.ReturnType = this.ElementType;
+ this.getterList = new MemberList();
+ this.getterList.Add(getter);
+ }
+ }
+ }
+ return (Method)this.getterList[0];
+ }
+ }
+ public Method Setter
+ {
+ get
+ {
+ if (this.setterList == null)
+ {
+ lock (this)
+ {
+ if (this.setterList == null)
+ {
+ Method setter = new Method();
+ setter.Name = StandardIds.Set;
+ setter.DeclaringType = this;
+ setter.CallingConvention = CallingConventionFlags.HasThis;
+ setter.Flags = MethodFlags.Public;
+ setter.Parameters = new ParameterList();
+ Parameter par;
+ for (int i = 0, n = this.Rank; i < n; i++)
+ {
+ par = new Parameter();
+ par.Type = CoreSystemTypes.Int32;
+ par.DeclaringMethod = setter;
+ setter.Parameters.Add(par);
+ }
+ par = new Parameter();
+ par.Type = this.ElementType;
+ par.DeclaringMethod = setter;
+ setter.Parameters.Add(par);
+ setter.ReturnType = CoreSystemTypes.Void;
+ this.setterList = new MemberList();
+ this.setterList.Add(setter);
+ }
+ }
+ }
+ return (Method)this.setterList[0];
+ }
+ }
+ public Method Address
+ {
+ get
+ {
+ if (this.addressList == null)
+ {
+ lock (this)
+ {
+ if (this.addressList == null)
+ {
+ Method address = new Method();
+ address.Name = StandardIds.Address;
+ address.DeclaringType = this;
+ address.CallingConvention = CallingConventionFlags.HasThis;
+ address.Flags = MethodFlags.Public;
+ address.Parameters = new ParameterList();
+ for (int i = 0, n = this.Rank; i < n; i++)
+ {
+ Parameter par = new Parameter();
+ par.Type = CoreSystemTypes.Int32;
+ par.DeclaringMethod = address;
+ address.Parameters.Add(par);
+ }
+ address.ReturnType = this.ElementType.GetReferenceType();
+ this.addressList = new MemberList();
+ this.addressList.Add(address);
+ }
+ }
+ }
+ return (Method)this.addressList[0];
+ }
+ }
+ public override bool IsAssignableTo(TypeNode targetType)
+ {
+ if (targetType == null) return false;
+ if (targetType == this || targetType == CoreSystemTypes.Object || targetType == CoreSystemTypes.Array || targetType == SystemTypes.ICloneable) return true;
+ if (CoreSystemTypes.Array.IsAssignableTo(targetType)) return true;
+ if (targetType.Template != null && SystemTypes.GenericIEnumerable != null && SystemTypes.GenericIEnumerable.DeclaringModule == CoreSystemTypes.SystemAssembly)
+ {
+ if (targetType.Template == SystemTypes.GenericIEnumerable || targetType.Template == SystemTypes.GenericICollection ||
+ targetType.Template == SystemTypes.GenericIList)
+ {
+ if (targetType.TemplateArguments == null || targetType.TemplateArguments.Count != 1)
+ {
+ Debug.Assert(false); return false;
+ }
+ TypeNode ienumElementType = targetType.TemplateArguments[0];
+ if (this.ElementType == ienumElementType) return true;
+ if (this.ElementType.IsValueType) return false;
+ return this.ElementType.IsAssignableTo(ienumElementType);
+ }
+ }
+ ArrayType targetArrayType = targetType as ArrayType;
+ if (targetArrayType == null) return false;
+ if (this.Rank != 1 || targetArrayType.Rank != 1) return false;
+ TypeNode thisElementType = this.ElementType;
+ if (thisElementType == null) return false;
+#if ExtendedRuntime
+ thisElementType = TypeNode.StripModifier(thisElementType, ExtendedRuntimeTypes.NonNullType);
+ // DelayedAttribute is used as a modifier on some array allocation types to mark it as
+ // an explictly delayed allocation.
+ thisElementType = TypeNode.StripModifier(thisElementType, ExtendedRuntimeTypes.DelayedAttribute);
+#endif
+ if (thisElementType == targetArrayType.ElementType) return true;
+ if (thisElementType.IsValueType) return false;
+ return thisElementType.IsAssignableTo(targetArrayType.ElementType);
+ }
+ public override bool IsStructural
+ {
+ get { return true; }
+ }
+ protected TypeNodeList structuralElementTypes;
+ public override TypeNodeList StructuralElementTypes
+ {
+ get
+ {
+ TypeNodeList result = this.structuralElementTypes;
+ if (result != null) return result;
+ this.structuralElementTypes = result = new TypeNodeList(1);
+ result.Add(this.ElementType);
+ return result;
+ }
+ }
+ public override bool IsStructurallyEquivalentTo(TypeNode type)
+ {
+ if (type == null) return false;
+ if (this == type) return true;
+ ArrayType t = type as ArrayType;
+ if (t == null) return false;
+ if (this.Rank != t.Rank) return false;
+ if (this.ElementType == null || t.ElementType == null) return false;
+ if (this.ElementType != t.ElementType && !this.ElementType.IsStructurallyEquivalentTo(t.ElementType)) return false;
+ if (this.Sizes == null) return t.Sizes == null;
+ if (t.Sizes == null) return false;
+ int n = this.Sizes.Length; if (n != t.Sizes.Length) return false;
+ for (int i = 0; i < n; i++)
+ {
+ if (this.Sizes[i] != t.Sizes[i]) return false;
+ }
+ if (this.LowerBounds == null) return t.LowerBounds == null;
+ if (t.LowerBounds == null) return false;
+ n = this.LowerBounds.Length; if (n != t.LowerBounds.Length) return false;
+ for (int i = 0; i < n; i++)
+ {
+ if (this.LowerBounds[i] != t.LowerBounds[i]) return false;
+ }
+ return true;
+ }
+#if FxCop
+ internal override void GetName(MemberFormat options, StringBuilder name)
+ {
+ this.ElementType.GetName(options, name);
+ GetNameSuffix(name, options.InsertSpacesBetweenMethodTypeParameters);
+ }
+ private void GetNameSuffix(StringBuilder name, bool insertSpacesBetweenParameters)
+ {
+ name.Append('[');
+ int k = this.Sizes == null ? 0 : this.Sizes.Length;
+ int m = this.LowerBounds == null ? 0 : this.LowerBounds.Length;
+ for (int i = 0, n = this.Rank; i < n; i++)
+ {
+ if (i < k && this.Sizes[i] != 0)
+ {
+ if (i < m && this.LowerBounds[i] != 0)
+ {
+ name.Append(this.LowerBounds[i].ToString("0", CultureInfo.InvariantCulture));
+ name.Append(':');
+ }
+ name.Append(this.Sizes[i].ToString("0", CultureInfo.InvariantCulture));
+ }
+ if (i < n - 1)
+ {
+ name.Append(',');
+ if (insertSpacesBetweenParameters)
+ name.Append(' ');
+ }
+ }
+ name.Append(']');
+ }
+#endif
+ }
+ public class Pointer : TypeNode
+ {
+ internal Pointer(TypeNode/*!*/ elementType)
+ : base(NodeType.Pointer)
+ {
+ this.elementType = elementType;
+ this.typeCode = Metadata.ElementType.Pointer;
+ this.Name = Identifier.For(elementType.Name + "*");
+ this.Namespace = elementType.Namespace;
+ }
+ private TypeNode/*!*/ elementType;
+ public TypeNode/*!*/ ElementType
+ {
+ get { return this.elementType; }
+ set { this.elementType = value; }
+ }
+ public override string/*!*/ FullName
+ {
+ get
+ {
+ if (this.ElementType != null && this.ElementType.DeclaringType != null)
+ return this.ElementType.DeclaringType.FullName + "+" + (this.Name == null ? "" : this.Name.ToString());
+ else if (this.Namespace != null && this.Namespace.UniqueIdKey != Identifier.Empty.UniqueIdKey)
+ return this.Namespace.ToString() + "." + (this.Name == null ? "" : this.Name.ToString());
+ else if (this.Name != null)
+ return this.Name.ToString();
+ else
+ return "";
+ }
+ }
+#if !NoXml
+ internal override void AppendDocumentIdMangledName(StringBuilder/*!*/ sb, TypeNodeList methodTypeParameters, TypeNodeList typeParameters)
+ {
+ if (this.elementType == null) return;
+ this.elementType.AppendDocumentIdMangledName(sb, methodTypeParameters, typeParameters);
+ sb.Append('*');
+ }
+#endif
+#if !NoReflection
+ public override Type GetRuntimeType()
+ {
+ if (this.runtimeType == null)
+ {
+ if (this.ElementType == null) return null;
+ Type eType = this.ElementType.GetRuntimeType();
+ if (eType == null) return null;
+#if WHIDBEY
+ this.runtimeType = eType.MakePointerType();
+#else
+ if (eType.Assembly != null)
+ this.runtimeType = eType.Assembly.GetType(eType.FullName+"*", false);
+ else
+ this.runtimeType = eType.Module.GetType(eType.FullName+"*", false);
+#endif
+ }
+ return this.runtimeType;
+ }
+#endif
+ public override bool IsAssignableTo(TypeNode targetType)
+ {
+ return targetType == this || (targetType is Pointer && ((Pointer)targetType).ElementType == CoreSystemTypes.Void);
+ }
+ public override bool IsUnmanaged
+ {
+ get
+ {
+ return true;
+ }
+ }
+ public override bool IsStructural
+ {
+ get { return true; }
+ }
+ public override bool IsPointerType
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ protected TypeNodeList structuralElementTypes;
+ public override TypeNodeList StructuralElementTypes
+ {
+ get
+ {
+ TypeNodeList result = this.structuralElementTypes;
+ if (result != null) return result;
+ this.structuralElementTypes = result = new TypeNodeList(1);
+ result.Add(this.ElementType);
+ return result;
+ }
+ }
+ public override bool IsStructurallyEquivalentTo(TypeNode type)
+ {
+ if (type == null) return false;
+ if (this == type) return true;
+ Pointer t = type as Pointer;
+ if (t == null) return false;
+ if (this.ElementType == null || t.ElementType == null) return false;
+ return this.ElementType == t.ElementType || this.ElementType.IsStructurallyEquivalentTo(t.ElementType);
+ }
+#if FxCop
+ internal override void GetName(TypeFormat options, StringBuilder name)
+ {
+ this.ElementType.GetName(options, name);
+ name.Append('*');
+ }
+#endif
+ }
+ public class Reference : TypeNode
+ {
+ internal Reference(TypeNode/*!*/ elementType)
+ : base(NodeType.Reference)
+ {
+ this.elementType = elementType;
+ this.typeCode = Metadata.ElementType.Reference;
+ this.Name = Identifier.For(elementType.Name + "@");
+ this.Namespace = elementType.Namespace;
+ }
+ private TypeNode/*!*/ elementType;
+ public TypeNode/*!*/ ElementType
+ {
+ get { return this.elementType; }
+ set { this.elementType = value; }
+ }
+#if !NoXml
+ internal override void AppendDocumentIdMangledName(StringBuilder/*!*/ sb, TypeNodeList methodTypeParameters, TypeNodeList typeParameters)
+ {
+ if (this.elementType == null) return;
+ this.elementType.AppendDocumentIdMangledName(sb, methodTypeParameters, typeParameters);
+ sb.Append('@');
+ }
+#endif
+ public override bool IsAssignableTo(TypeNode targetType)
+ {
+ return targetType == this ||
+ (targetType is Pointer && (((Pointer)targetType).ElementType == this.ElementType ||
+ ((Pointer)targetType).ElementType == CoreSystemTypes.Void));
+ }
+
+ public override string/*!*/ FullName
+ {
+ get
+ {
+ if (this.ElementType != null && this.ElementType.DeclaringType != null)
+ return this.ElementType.DeclaringType.FullName + "+" + (this.Name == null ? "" : this.Name.ToString());
+ else if (this.Namespace != null && this.Namespace.UniqueIdKey != Identifier.Empty.UniqueIdKey)
+ return this.Namespace.ToString() + "." + (this.Name == null ? "" : this.Name.ToString());
+ else if (this.Name != null)
+ return this.Name.ToString();
+ else
+ return "";
+ }
+ }
+#if !NoReflection
+ public override Type GetRuntimeType()
+ {
+ if (this.runtimeType == null)
+ {
+ if (this.ElementType == null) return null;
+ Type eType = this.ElementType.GetRuntimeType();
+ if (eType == null) return null;
+#if WHIDBEY
+ this.runtimeType = eType.MakeByRefType();
+#else
+ if (eType.Assembly != null)
+ this.runtimeType = eType.Assembly.GetType(eType.FullName+"&", false);
+ else
+ this.runtimeType = eType.Module.GetType(eType.FullName+"&", false);
+#endif
+ }
+ return this.runtimeType;
+ }
+#endif
+ public override bool IsStructural
+ {
+ get { return true; }
+ }
+ protected TypeNodeList structuralElementTypes;
+ public override TypeNodeList StructuralElementTypes
+ {
+ get
+ {
+ TypeNodeList result = this.structuralElementTypes;
+ if (result != null) return result;
+ this.structuralElementTypes = result = new TypeNodeList(1);
+ result.Add(this.ElementType);
+ return result;
+ }
+ }
+ public override bool IsStructurallyEquivalentTo(TypeNode type)
+ {
+ if (type == null) return false;
+ if (this == type) return true;
+ Reference t = type as Reference;
+ if (t == null) return false;
+ if (this.ElementType == null || t.ElementType == null) return false;
+ return this.ElementType == t.ElementType || this.ElementType.IsStructurallyEquivalentTo(t.ElementType);
+ }
+#if FxCop
+ internal override void GetName(TypeFormat options, StringBuilder name)
+ {
+ this.ElementType.GetName(options, name);
+ name.Append('&');
+ }
+#endif
+ }
+#if ExtendedRuntime
+ public class TupleType : Struct{
+ private TupleType(FieldList domains, Identifier/*!*/ name, TypeNode/*!*/ referringType, TypeFlags visibility) {
+ referringType.DeclaringModule.StructurallyEquivalentType[name.UniqueIdKey] = this;
+ this.DeclaringModule = referringType.DeclaringModule;
+ this.NodeType = NodeType.TupleType;
+ this.Flags = TypeFlags.Sealed;
+ this.Namespace = StandardIds.StructuralTypes;
+ this.Name = name;
+ this.isNormalized = true;
+ switch (visibility){
+ case TypeFlags.NestedFamANDAssem:
+ case TypeFlags.NestedFamily:
+ case TypeFlags.NestedPrivate:
+ referringType.Members.Add(this);
+ this.DeclaringType = referringType;
+ this.Flags |= TypeFlags.NestedPrivate;
+ break;
+ default:
+ referringType.DeclaringModule.Types.Add(this);
+ this.Flags |= TypeFlags.Public;
+ break;
+ }
+ int n = domains == null ? 0 : domains.Count;
+ MemberList members = this.members = new MemberList(n);
+ TypeNodeList types = new TypeNodeList(n);
+ for (int i = 0; i < n; i++){
+ //^ assert domains != null;
+ Field f = domains[i];
+ if (f == null) continue;
+ f = (Field)f.Clone();
+ f.DeclaringType = this;
+ members.Add(f);
+ if (f.Type != null)
+ types.Add(f.Type);
+ }
+ TypeNode elemType = null;
+ if (n == 1)
+ elemType = types[0]; //TODO: get element type of stream?
+ else{
+ TypeUnion tu = TypeUnion.For(types, referringType);
+ //^ assume tu != null;
+ elemType = tu;
+ if (tu.Types.Count == 1) elemType = tu.Types[0];
+ }
+ if (elemType == null) elemType = CoreSystemTypes.Object;
+ Interface ienumerable = (Interface)SystemTypes.GenericIEnumerable.GetTemplateInstance(referringType, elemType);
+ Interface ienumerator = (Interface)SystemTypes.GenericIEnumerator.GetTemplateInstance(referringType, elemType);
+ this.Interfaces = new InterfaceList(SystemTypes.TupleType, ienumerable, SystemTypes.IEnumerable);
+
+ This ThisParameter = new This(this.GetReferenceType());
+ StatementList statements = new StatementList(1);
+ TypeNode tEnumerator = TupleEnumerator.For(this, n, elemType, ienumerator, referringType);
+ InstanceInitializer cons = tEnumerator.GetConstructor(this);
+ if (cons == null) { Debug.Fail(""); return; }
+ ExpressionList args = new ExpressionList(new AddressDereference(ThisParameter, this));
+ statements.Add(new Return(new Construct(new MemberBinding(null, cons), args)));
+ Block body = new Block(statements);
+ Method getEnumerator = new Method(this, null, StandardIds.GetEnumerator, null, ienumerator, body);
+ getEnumerator.Flags = MethodFlags.Public|MethodFlags.Virtual;
+ getEnumerator.CallingConvention = CallingConventionFlags.HasThis;
+ getEnumerator.ThisParameter = ThisParameter;
+ this.members.Add(getEnumerator);
+
+ //IEnumerable.GetEnumerator
+ ThisParameter = new This(this.GetReferenceType());
+ statements = new StatementList(1);
+ MethodCall mcall = new MethodCall(new MemberBinding(ThisParameter, getEnumerator), new ExpressionList(0), NodeType.Call, SystemTypes.IEnumerator);
+ statements.Add(new Return(mcall));
+ getEnumerator = new Method(this, null, StandardIds.IEnumerableGetEnumerator, null, SystemTypes.IEnumerator, new Block(statements));
+ getEnumerator.ThisParameter = ThisParameter;
+ getEnumerator.ImplementedInterfaceMethods = new MethodList(SystemTypes.IEnumerable.GetMethod(StandardIds.GetEnumerator));
+ getEnumerator.CallingConvention = CallingConventionFlags.HasThis;
+ getEnumerator.Flags = MethodFlags.Private | MethodFlags.Virtual | MethodFlags.SpecialName;
+ this.members.Add(getEnumerator);
+ }
+ internal TupleType(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
+ : base(provideNestedTypes, provideAttributes, provideMembers, handle) {
+ this.NodeType = NodeType.TupleType;
+ this.typeCode = ElementType.ValueType;
+ }
+ public static TupleType For(FieldList domains, TypeNode referringType){
+ if (referringType == null) return null;
+ Module module = referringType.DeclaringModule;
+ if (module == null) return null;
+ TypeFlags visibility = TypeFlags.Public;
+ StringBuilder name = new StringBuilder();
+ name.Append("Tuple");
+ int n = domains == null ? 0 : domains.Count;
+ for (int i = 0; i < n; i++) {
+ //^ assert domains != null;
+ Field f = domains[i];
+ if (f == null || f.Type == null || f.Type.Name == null) continue;
+ visibility = TypeNode.GetVisibilityIntersection(visibility, f.Type.Flags & TypeFlags.VisibilityMask);
+ name.Append('_');
+ name.Append(f.Type.Name.ToString());
+ if (f.Name != null && !f.IsSpecialName) {
+ name.Append('_');
+ name.Append(f.Name.ToString());
+ }
+ }
+ TupleType tup = null;
+ int tCount = 0;
+ string tNameString = name.ToString();
+ Identifier tName = Identifier.For(tNameString);
+ TypeNode result = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, tName);
+ while (result != null) {
+ //Mangled name is the same. But mangling is not unique (types are not qualified with assemblies), so check for equality.
+ tup = result as TupleType;
+ bool goodMatch = tup != null;
+ if (goodMatch) {
+ //^ assert tup != null;
+ MemberList tMembers = tup.Members;
+ int m = tMembers == null ? 0 : tMembers.Count;
+ goodMatch = n == m-2;
+ if (goodMatch) {
+ //^ assert domains != null;
+ //^ assert tMembers != null;
+ for (int i = 0; goodMatch && i < n; i++) {
+ Field f1 = domains[i];
+ Field f2 = tMembers[i] as Field;
+ goodMatch = f1 != null && f2 != null && f1.Type == f2.Type &&
+ f1.Name != null && f2.Name != null && f1.Name.UniqueIdKey == f2.Name.UniqueIdKey;
+ }
+ }
+ }
+ if (goodMatch) return tup;
+ //Mangle some more
+ tName = Identifier.For(tNameString+(++tCount).ToString());
+ result = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, tName);
+ }
+ tup = new TupleType(domains, tName, referringType, visibility);
+ return tup;
+ }
+ public override bool IsStructural{
+ get{return true;}
+ }
+ protected TypeNodeList structuralElementTypes;
+ public override TypeNodeList StructuralElementTypes{
+ get{
+ TypeNodeList result = this.structuralElementTypes;
+ if (result != null) return result;
+ this.structuralElementTypes = result = new TypeNodeList(1);
+ MemberList members = this.Members;
+ for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++){
+ Field f = members[i] as Field;
+ if (f == null || f.Type == null) continue;
+ result.Add(f.Type);
+ }
+ return result;
+ }
+ }
+ public override bool IsStructurallyEquivalentTo(TypeNode type){
+ if (type == null) return false;
+ if (this == type) return true;
+ TupleType t = type as TupleType;
+ if (t == null) return false;
+ if (this.Members == null) return t.Members == null;
+ if (t.Members == null) return false;
+ int n = this.Members.Count; if (n != t.Members.Count) return false;
+ for (int i = 0; i < n; i++){
+ Member m1 = this.Members[i];
+ Member m2 = t.Members[i];
+ if (m1 == null || m2 == null) return false;
+ Field f1 = m1 as Field;
+ Field f2 = m2 as Field;
+ if (f1 == null && f2 == null) continue;
+ if (f1 == null || f2 == null) return false;
+ if (f1.Name == null || f2.Name == null) return false;
+ if (f1.Type == null || f2.Type == null) return false;
+ if (f1.Name.UniqueIdKey != f2.Name.UniqueIdKey) return false;
+ if (f1.Type != f2.Type && !f1.Type.IsStructurallyEquivalentTo(f2.Type)) return false;
+ }
+ return true;
+ }
+ }
+ internal sealed class TupleEnumerator{
+ private TupleEnumerator(){}
+ internal static TypeNode/*!*/ For(TupleType/*!*/ tuple, int numDomains, TypeNode/*!*/ elementType, Interface/*!*/ targetIEnumerator, TypeNode/*!*/ referringType) {
+ Identifier id = Identifier.For("Enumerator"+tuple.Name);
+ InterfaceList interfaces = new InterfaceList(targetIEnumerator, SystemTypes.IDisposable, SystemTypes.IEnumerator);
+ MemberList members = new MemberList(5);
+ Class enumerator = new Class(referringType.DeclaringModule, null, null, TypeFlags.Sealed, targetIEnumerator.Namespace, id, CoreSystemTypes.Object, interfaces, members);
+ enumerator.IsNormalized = true;
+ if ((tuple.Flags & TypeFlags.VisibilityMask) == TypeFlags.Public){
+ enumerator.Flags |= TypeFlags.Public;
+ referringType.DeclaringModule.Types.Add(enumerator);
+ }else{
+ enumerator.Flags |= TypeFlags.NestedPrivate;
+ referringType.Members.Add(enumerator);
+ enumerator.DeclaringType = referringType;
+ }
+ //Field to hold tuple
+ Field tField = new Field(enumerator, null, FieldFlags.Private, StandardIds.Value, tuple, null);
+ members.Add(tField);
+ //Field to hold current position
+ Field pField = new Field(enumerator, null, FieldFlags.Private, StandardIds.Position, CoreSystemTypes.Int32, null);
+ members.Add(pField);
+ //Constructor
+ Parameter par = new Parameter(null, ParameterFlags.None, StandardIds.Value, tuple, null, null);
+ StatementList statements = new StatementList(4);
+ InstanceInitializer constr = CoreSystemTypes.Object.GetConstructor();
+ if (constr == null) { Debug.Fail(""); return enumerator; }
+ This thisParameter = new This(enumerator);
+ MethodCall mcall = new MethodCall(new MemberBinding(thisParameter, constr), new ExpressionList(0), NodeType.Call, CoreSystemTypes.Void);
+ statements.Add(new ExpressionStatement(mcall));
+ statements.Add(new AssignmentStatement(new MemberBinding(thisParameter, tField), par));
+ statements.Add(new AssignmentStatement(new MemberBinding(thisParameter, pField), Literal.Int32MinusOne));
+ statements.Add(new Return());
+ InstanceInitializer econs = new InstanceInitializer(enumerator, null, new ParameterList(par), new Block(statements));
+ econs.ThisParameter = thisParameter;
+ econs.Flags |= MethodFlags.Public;
+ members.Add(econs);
+ //get_Current
+ thisParameter = new This(enumerator);
+ statements = new StatementList(numDomains+1);
+ BlockList blocks = new BlockList(numDomains);
+ statements.Add(new SwitchInstruction(new MemberBinding(thisParameter, pField), blocks));
+ constr = SystemTypes.InvalidOperationException.GetConstructor();
+ if (constr == null) { Debug.Fail(""); return enumerator; }
+ statements.Add(new Throw(new Construct(new MemberBinding(null, constr), null)));
+ for (int i = 0; i < numDomains; i++){
+ Field f = (Field)tuple.members[i];
+ MemberBinding mb = new MemberBinding(new UnaryExpression(new MemberBinding(thisParameter, tField), NodeType.AddressOf), f);
+ Block b = new Block();
+ statements.Add(b);
+ blocks.Add(b);
+ if (f.Type == elementType || f.Type == null)
+ b.Statements = new StatementList(new Return(mb));
+ else{
+ TypeUnion tUnion = elementType as TypeUnion;
+ Debug.Assert(tUnion != null);
+ if (tUnion != null){
+ Method m = tUnion.GetImplicitCoercionFromMethod(f.Type);
+ if (m != null){
+ MethodCall mCall = new MethodCall(new MemberBinding(null, m), new ExpressionList(mb));
+ b.Statements = new StatementList(new Return(mCall));
+ }else{
+ TypeUnion eUnion = f.Type as TypeUnion;
+ if (eUnion != null){
+ Method getTagAsType = eUnion.GetMethod(StandardIds.GetTagAsType);
+ Method getValue = eUnion.GetMethod(StandardIds.GetValue);
+ Method fromObject = tUnion.GetMethod(StandardIds.FromObject, CoreSystemTypes.Object, CoreSystemTypes.Type);
+ if (getTagAsType == null || getValue == null || fromObject == null) {
+ Debug.Fail(""); return enumerator;
+ }
+ Local temp = new Local(Identifier.Empty, eUnion);
+ Expression tempAddr = new UnaryExpression(temp, NodeType.AddressOf);
+ StatementList stats = new StatementList(2);
+ stats.Add(new AssignmentStatement(temp, mb));
+ ExpressionList arguments = new ExpressionList(2);
+ arguments.Add(new MethodCall(new MemberBinding(tempAddr, getValue), null));
+ arguments.Add(new MethodCall(new MemberBinding(tempAddr, getTagAsType), null));
+ stats.Add(new Return(new MethodCall(new MemberBinding(null, fromObject), arguments)));
+ b.Statements = stats;
+ }else{
+ Debug.Assert(false);
+ }
+ }
+ }
+ }
+ }
+ Method getCurrent = new Method(enumerator, null, StandardIds.getCurrent, null, elementType, new Block(statements));
+ getCurrent.Flags = MethodFlags.Public|MethodFlags.Virtual|MethodFlags.NewSlot|MethodFlags.HideBySig|MethodFlags.SpecialName;
+ getCurrent.CallingConvention = CallingConventionFlags.HasThis;
+ getCurrent.ThisParameter = thisParameter;
+ members.Add(getCurrent);
+
+ //IEnumerator.GetCurrent
+ statements = new StatementList(1);
+ This ThisParameter = new This(enumerator);
+ MethodCall callGetCurrent = new MethodCall(new MemberBinding(ThisParameter, getCurrent), new ExpressionList(0), NodeType.Call, elementType);
+ MemberBinding etExpr = new MemberBinding(null, elementType);
+ statements.Add(new Return(new BinaryExpression(callGetCurrent, etExpr, NodeType.Box, CoreSystemTypes.Object)));
+ Method ieGetCurrent = new Method(enumerator, null, StandardIds.IEnumeratorGetCurrent, null, CoreSystemTypes.Object, new Block(statements));
+ ieGetCurrent.ThisParameter = ThisParameter;
+ ieGetCurrent.ImplementedInterfaceMethods = new MethodList(SystemTypes.IEnumerator.GetMethod(StandardIds.getCurrent));
+ ieGetCurrent.CallingConvention = CallingConventionFlags.HasThis;
+ ieGetCurrent.Flags = MethodFlags.Private|MethodFlags.Virtual|MethodFlags.SpecialName;
+ members.Add(ieGetCurrent);
+
+ //IEnumerator.Reset
+ statements = new StatementList(2);
+ ThisParameter = new This(enumerator);
+ statements.Add(new AssignmentStatement(new MemberBinding(ThisParameter, pField), Literal.Int32Zero));
+ statements.Add(new Return());
+ Method reset = new Method(enumerator, null, StandardIds.IEnumeratorReset, null, CoreSystemTypes.Void, new Block(statements));
+ reset.ThisParameter = ThisParameter;
+ reset.ImplementedInterfaceMethods = new MethodList(SystemTypes.IEnumerator.GetMethod(StandardIds.Reset));
+ reset.CallingConvention = CallingConventionFlags.HasThis;
+ reset.Flags = MethodFlags.Private|MethodFlags.Virtual|MethodFlags.SpecialName;
+ members.Add(reset);
+
+ //MoveNext
+ ThisParameter = new This(enumerator);
+ statements = new StatementList(5);
+ MemberBinding pos = new MemberBinding(ThisParameter, pField);
+ Expression comparison = new BinaryExpression(pos, new Literal(numDomains, CoreSystemTypes.Int32), NodeType.Lt);
+ Block returnTrue = new Block();
+ statements.Add(new AssignmentStatement(pos, new BinaryExpression(pos, Literal.Int32One, NodeType.Add)));
+ statements.Add(new Branch(comparison, returnTrue));
+ statements.Add(new Return(Literal.False));
+ statements.Add(returnTrue);
+ statements.Add(new Return(Literal.True));
+ Method moveNext = new Method(enumerator, null, StandardIds.MoveNext, null, CoreSystemTypes.Boolean, new Block(statements));
+ moveNext.Flags = MethodFlags.Public|MethodFlags.Virtual|MethodFlags.NewSlot|MethodFlags.HideBySig;
+ moveNext.CallingConvention = CallingConventionFlags.HasThis;
+ moveNext.ThisParameter = ThisParameter;
+ members.Add(moveNext);
+ //IDispose.Dispose
+ statements = new StatementList(1);
+ statements.Add(new Return());
+ Method dispose = new Method(enumerator, null, StandardIds.Dispose, null, CoreSystemTypes.Void, new Block(statements));
+ dispose.CallingConvention = CallingConventionFlags.HasThis;
+ dispose.Flags = MethodFlags.Public|MethodFlags.Virtual;
+ enumerator.Members.Add(dispose);
+ return enumerator;
+ }
+ }
+ public class TypeAlias : Struct{
+ protected TypeNode aliasedType;
+ public TypeNode AliasedTypeExpression;
+ public bool RequireExplicitCoercionFromUnderlyingType;
+ public TypeAlias()
+ : this(null, null){
+ }
+ internal TypeAlias(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle, bool requireExplicitCoercionFromUnderlyingType)
+ : base(provideNestedTypes, provideAttributes, provideMembers, handle) {
+ this.RequireExplicitCoercionFromUnderlyingType = requireExplicitCoercionFromUnderlyingType;
+ }
+ public TypeAlias(TypeNode aliasedType, Identifier name)
+ : base(){
+ this.NodeType = NodeType.TypeAlias;
+ this.AliasedType = aliasedType;
+ this.Name = name;
+ }
+ public TypeNode AliasedType{
+ get{
+ if (this.aliasedType == null){
+ Field f = this.GetField(StandardIds.Value);
+ if (f != null)
+ this.aliasedType = f.Type;
+ }
+ return this.aliasedType;
+ }
+ set{
+ this.aliasedType = value;
+ }
+ }
+ public virtual void ProvideMembers(){
+ if (this.AliasedType == null) return;
+ this.Interfaces = new InterfaceList(1);
+ if (this.RequireExplicitCoercionFromUnderlyingType)
+ this.Interfaces.Add(SystemTypes.TypeDefinition);
+ else
+ this.Interfaces.Add(SystemTypes.TypeAlias);
+ MemberList members = this.members;
+ if (members == null) members = this.members = new MemberList();
+ //Value field
+ Field valueField = new Field(this, null, FieldFlags.Private, StandardIds.Value, this.AliasedType, null);
+ members.Add(valueField);
+ //Implicit conversion from this type to underlying type
+ ParameterList parameters = new ParameterList(1);
+ Parameter valuePar = new Parameter(null, ParameterFlags.None, StandardIds.Value, this, null, null);
+ parameters.Add(valuePar);
+ Method toAliasedType = new Method(this, null, StandardIds.opImplicit, parameters, this.AliasedType, null);
+ toAliasedType.Flags = MethodFlags.Static|MethodFlags.SpecialName|MethodFlags.Public;
+ members.Add(toAliasedType);
+ StatementList statements = new StatementList(1);
+ statements.Add(new Return(new MemberBinding(new UnaryExpression(valuePar, NodeType.AddressOf), valueField)));
+ toAliasedType.Body = new Block(statements);
+ //Implicit or explicit conversion from underlying type to this type
+ Identifier opId = this.RequireExplicitCoercionFromUnderlyingType ? StandardIds.opExplicit : StandardIds.opImplicit;
+ parameters = new ParameterList(1);
+ parameters.Add(valuePar = new Parameter(null, ParameterFlags.None, StandardIds.Value, this.AliasedType, null, null));
+ Method fromAliasedType = new Method(this, null, opId, parameters, this, null);
+ fromAliasedType.Flags = MethodFlags.Static|MethodFlags.SpecialName|MethodFlags.Public;
+ members.Add(fromAliasedType);
+ statements = new StatementList(2);
+ Local loc = new Local(this);
+ statements.Add(new AssignmentStatement(new MemberBinding(new UnaryExpression(loc, NodeType.AddressOf), valueField), valuePar));
+ statements.Add(new Return(loc));
+ fromAliasedType.Body = new Block(statements);
+ this.AddCoercionWrappers(this.AliasedType.ExplicitCoercionMethods, StandardIds.opExplicit, fromAliasedType, toAliasedType);
+ this.AddCoercionWrappers(this.AliasedType.ImplicitCoercionMethods, StandardIds.opImplicit, fromAliasedType, toAliasedType);
+ }
+ private void AddCoercionWrappers(MemberList coercions, Identifier id, Method/*!*/ fromAliasedType, Method/*!*/ toAliasedType)
+ //^ requires this.members != null;
+ {
+ if (coercions == null) return;
+ MemberList members = this.members;
+ for (int i = 0, n = coercions.Count; i < n; i++){
+ Method coercion = coercions[i] as Method;
+ if (coercion == null || coercion.Parameters == null || coercion.Parameters.Count != 1) continue;
+ ParameterList parameters = new ParameterList(1);
+ Parameter valuePar = new Parameter(null, ParameterFlags.None, StandardIds.Value, null, null, null);
+ parameters.Add(valuePar);
+ Method m = new Method(this, null, id, parameters, null, null);
+ m.Flags = MethodFlags.Static|MethodFlags.SpecialName|MethodFlags.Public;
+ Expression arg = valuePar;
+ MethodCall call = new MethodCall(new MemberBinding(null, coercion), new ExpressionList(arg));
+ if (coercion.ReturnType == this.AliasedType){
+ m.ReturnType = this;
+ if (this.RequireExplicitCoercionFromUnderlyingType) m.Name = StandardIds.opExplicit;
+ valuePar.Type = coercion.Parameters[0].Type;
+ call = new MethodCall(new MemberBinding(null, fromAliasedType), new ExpressionList(call));
+ }else{
+ m.ReturnType = coercion.ReturnType;
+ valuePar.Type = this;
+ //^ assume call.Operands != null;
+ call.Operands[0] = new MethodCall(new MemberBinding(null, toAliasedType), new ExpressionList(arg));
+ }
+ m.Body = new Block(new StatementList(new Return(call)));
+ members.Add(m);
+ }
+ }
+ public override bool IsStructural{
+ get{return this.RequireExplicitCoercionFromUnderlyingType;}
+ }
+ protected TypeNodeList structuralElementTypes;
+ public override TypeNodeList StructuralElementTypes{
+ get{
+ TypeNodeList result = this.structuralElementTypes;
+ if (result != null) return result;
+ this.structuralElementTypes = result = new TypeNodeList(1);
+ result.Add(this.AliasedType);
+ return result;
+ }
+ }
+ public override bool IsStructurallyEquivalentTo(TypeNode type){
+ if (type == null) return false;
+ if (this == type) return true;
+ if (this.RequireExplicitCoercionFromUnderlyingType) return false;
+ TypeAlias t = type as TypeAlias;
+ if (t == null) return false;
+ if (t.RequireExplicitCoercionFromUnderlyingType) return false;
+ if (this.AliasedType == null || t.AliasedType == null) return false;
+ return this.AliasedType == t.AliasedType || this.AliasedType.IsStructurallyEquivalentTo(t.AliasedType);
+ }
+ }
+ public class TypeIntersection : Struct{
+ private TypeNodeList types; //sorted by UniqueKey
+ public TypeNodeList Types{
+ get{
+ if (this.types != null) return this.types;
+ if (this.ProvideTypeMembers != null) { MemberList mems = this.Members; if (mems != null) mems = null; }
+ return this.types;
+ }
+ set{
+ this.types = value;
+ }
+ }
+
+ private TypeIntersection(TypeNodeList types, Identifier name) {
+ this.NodeType = NodeType.TypeIntersection;
+ this.Flags = TypeFlags.Public|TypeFlags.Sealed;
+ this.Namespace = StandardIds.StructuralTypes;
+ this.Name = name;
+ this.Types = types;
+ int n = types == null ? 0 : types.Count;
+ InterfaceList ifaces = this.Interfaces = new InterfaceList(n+1);
+ ifaces.Add(SystemTypes.TypeIntersection);
+ if (types != null)
+ for (int i = 0; i < n; i++){
+ Interface iface = types[i] as Interface;
+ if (iface == null) continue;
+ ifaces.Add(iface);
+ }
+ this.isNormalized = true;
+ }
+ internal TypeIntersection(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
+ : base(provideNestedTypes, provideAttributes, provideMembers, handle) {
+ this.NodeType = NodeType.TypeIntersection;
+ this.typeCode = ElementType.ValueType;
+ }
+ public static TypeIntersection For(TypeNodeList types, Module module) {
+ if (module == null) return null;
+ if (types != null && !TypeUnion.AreNormalized(types))
+ types = TypeUnion.Normalize(types);
+ TypeFlags visibility = TypeFlags.Public;
+ string name = TypeUnion.BuildName(types, "And", ref visibility);
+ Identifier tName = Identifier.For(name);
+ int tCount = 0;
+ TypeIntersection result = null;
+ TypeNode t = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, tName);
+ while (t != null){
+ //Mangled name is the same. But mangling is not unique, so check for equality.
+ TypeIntersection ti = t as TypeIntersection;
+ if (ti != null){
+ TypeNodeList ts = ti.Types;
+ int n = types == null ? 0 : types.Count;
+ bool goodMatch = ts != null && ts.Count == n;
+ for (int i = 0; goodMatch && i < n; i++) {
+ //^ assert types != null && ts != null;
+ goodMatch = types[i] == ts[i];
+ }
+ if (goodMatch) return ti;
+ }
+ //Mangle some more
+ tName = Identifier.For(name+(++tCount).ToString());
+ t = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, tName);
+ }
+ result = new TypeIntersection(types, tName);
+ result.DeclaringModule = module;
+ module.Types.Add(result);
+ module.StructurallyEquivalentType[tName.UniqueIdKey] = result;
+ return result;
+ }
+ public static TypeIntersection For(TypeNodeList types, TypeNode referringType) {
+ if (referringType == null) return null;
+ Module module = referringType.DeclaringModule;
+ if (module == null) return null;
+ if (types != null && !TypeUnion.AreNormalized(types))
+ types = TypeUnion.Normalize(types);
+ TypeFlags visibility = TypeFlags.Public;
+ string name = TypeUnion.BuildName(types, "And", ref visibility);
+ Identifier tName = Identifier.For(name);
+ int tCount = 0;
+ TypeIntersection result = null;
+ TypeNode t = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, tName);
+ while (t != null){
+ //Mangled name is the same. But mangling is not unique, so check for equality.
+ TypeIntersection ti = t as TypeIntersection;
+ if (ti != null){
+ TypeNodeList ts = ti.Types;
+ int n = types == null ? 0 : types.Count;
+ bool goodMatch = ts != null && ts.Count == n;
+ for (int i = 0; goodMatch && i < n; i++) {
+ //^ assert ts != null && types != null;
+ goodMatch = types[i] == ts[i];
+ }
+ if (goodMatch) return ti;
+ }
+ //Mangle some more
+ tName = Identifier.For(name+(++tCount).ToString());
+ t = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, tName);
+ }
+ result = new TypeIntersection(types, tName);
+ result.DeclaringModule = module;
+ switch (visibility){
+ case TypeFlags.NestedFamANDAssem:
+ case TypeFlags.NestedFamily:
+ case TypeFlags.NestedPrivate:
+ referringType.Members.Add(result);
+ result.DeclaringType = referringType;
+ result.Flags &= ~TypeFlags.VisibilityMask;
+ result.Flags |= TypeFlags.NestedPrivate;
+ break;
+ default:
+ module.Types.Add(result);
+ break;
+ }
+ module.StructurallyEquivalentType[tName.UniqueIdKey] = result;
+ return result;
+ }
+ public override bool IsAssignableTo(TypeNode targetType){
+ return targetType == this || targetType == CoreSystemTypes.Object;
+ }
+ public override bool IsStructural{
+ get{return true;}
+ }
+ protected TypeNodeList structuralElementTypes;
+ public override TypeNodeList StructuralElementTypes{
+ get{
+ TypeNodeList result = this.structuralElementTypes;
+ if (result != null) return result;
+ this.structuralElementTypes = result = new TypeNodeList(1);
+ TypeNodeList types = this.Types;
+ for (int i = 0, n = types == null ? 0 : types.Count; i < n; i++){
+ TypeNode t = types[i];
+ if (t == null) continue;
+ result.Add(t);
+ }
+ return result;
+ }
+ }
+ public override bool IsStructurallyEquivalentTo(TypeNode type){
+ if (type == null) return false;
+ if (this == type) return true;
+ TypeIntersection t = type as TypeIntersection;
+ if (t == null) return false;
+ return this.IsStructurallyEquivalentList(this.Types, t.Types);
+ }
+ private TrivialHashtable/*!*/ interfaceMethodFor = new TrivialHashtable();
+ public override MemberList Members{
+ get{
+ MemberList members = this.members;
+ if (members == null || this.membersBeingPopulated){
+ if (this.ProvideTypeMembers != null){
+ lock(this){
+ if (this.members != null) return this.members;
+ members = base.Members;
+ MemberList coercions = this.ExplicitCoercionMethods;
+ int n = coercions == null ? 0 : coercions.Count;
+ TypeNodeList typeList = this.Types = new TypeNodeList(n);
+ for (int i = 0; i < n; i++){
+ Method coercion = coercions[i] as Method;
+ if (coercion == null) continue;
+ typeList.Add(coercion.ReturnType);
+ }
+ }
+ return this.members;
+ }
+ members = this.Members = new MemberList();
+ //Value field
+ members.Add(new Field(this, null, FieldFlags.Private, StandardIds.Value, CoreSystemTypes.Object, null));
+ //FromObject
+ ParameterList parameters = new ParameterList(1);
+ parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.Value, CoreSystemTypes.Object, null, null));
+ Method m = new Method(this, null, StandardIds.FromObject, parameters, this, null);
+ m.Flags = MethodFlags.Static|MethodFlags.SpecialName|MethodFlags.Public;
+ members.Add(m);
+ //coercion operators
+ parameters = new ParameterList(1);
+ parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.Value, CoreSystemTypes.Object, null, null));
+ m = new Method(this, null, StandardIds.opExplicit, parameters, this, null);
+ m.Flags = MethodFlags.Static|MethodFlags.SpecialName|MethodFlags.Public;
+ members.Add(m);
+ parameters = new ParameterList(1);
+ parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.Value, this, null, null));
+ m = new Method(this, null, StandardIds.opImplicit, parameters, CoreSystemTypes.Object, null);
+ m.Flags = MethodFlags.Static|MethodFlags.SpecialName|MethodFlags.Public;
+ members.Add(m);
+ TypeNodeList types = this.Types;
+ for (int i = 0, n = types.Count; i < n; i++){
+ TypeNode t = types[i];
+ parameters = new ParameterList(1);
+ parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.Value, this, null, null));
+ m = new Method(this, null, StandardIds.opImplicit, parameters, t, null);
+ m.Flags = MethodFlags.Static|MethodFlags.SpecialName|MethodFlags.Public;
+ members.Add(m);
+ }
+ //Routines to forward interface calls to embedded object
+ InterfaceList ifaces = this.Interfaces;
+ if (ifaces != null){
+ for (int i = 0, n = ifaces.Count; i < n; i++){
+ Interface iface = ifaces[i];
+ if (iface == null) continue;
+ MemberList imembers = iface.Members;
+ if (imembers == null) continue;
+ for (int j = 0, k = imembers.Count; j < k; j++){
+ Method imeth = imembers[j] as Method;
+ if (imeth == null) continue;
+ if (imeth.IsStatic) continue;
+ Method meth = (Method)imeth.Clone();
+ meth.Flags &= ~MethodFlags.Abstract;
+ meth.DeclaringType = this;
+ members.Add(meth);
+ meth.Parameters = (imeth.Parameters == null ? null : imeth.Parameters.Clone());
+ for (int a = 0, b = meth.Parameters == null ? 0 : meth.Parameters.Count; a < b; a++){
+ Parameter par = meth.Parameters[a];
+ if (par == null) continue;
+ meth.Parameters[a] = par = (Parameter)par.Clone();
+ par.DeclaringMethod = meth;
+ }
+ this.interfaceMethodFor[meth.UniqueKey] = imeth;
+ }
+ }
+ }
+ this.ProvideBodiesForMethods();
+ }
+ return members;
+ }
+ set{
+ this.members = value;
+ }
+ }
+ private void ProvideBodiesForMethods()
+ //^ requires this.members != null;
+ {
+ MemberList members = this.members;
+ Field valueField = (Field)members[0];
+ //FromObject
+ Method fromObject = (Method)members[1];
+ StatementList statements = new StatementList(2);
+ Local resultLoc = new Local(Identifier.Empty, this);
+ Expression param = fromObject.Parameters[0];
+ statements.Add(new AssignmentStatement(new MemberBinding(new UnaryExpression(resultLoc, NodeType.AddressOf), valueField), param));
+ statements.Add(new Return(resultLoc));
+ fromObject.Body = new Block(statements);
+ //to coercion
+ Method toMethod = (Method)members[2];
+ statements = new StatementList(2);
+ resultLoc = new Local(Identifier.Empty, this);
+ param = toMethod.Parameters[0];
+ Expression castExpr = param;
+ TypeNodeList types = this.Types;
+ int n = types.Count;
+ for (int i = 0; i < n; i++){
+ TypeNode t = types[i];
+ castExpr = new BinaryExpression(castExpr, new Literal(t, CoreSystemTypes.Type), NodeType.Castclass);
+ }
+ statements.Add(new AssignmentStatement(new MemberBinding(new UnaryExpression(resultLoc, NodeType.AddressOf), valueField), castExpr));
+ statements.Add(new Return(resultLoc));
+ toMethod.Body = new Block(statements);
+ //from coercions
+ Method opImplicit = (Method)members[3];
+ opImplicit.Body = new Block(statements = new StatementList(1));
+ Expression val = new MemberBinding(new UnaryExpression(opImplicit.Parameters[0], NodeType.AddressOf), valueField);
+ statements.Add(new Return(val));
+ for (int i = 0; i < n; i++){
+ TypeNode t = types[i];
+ opImplicit = (Method)members[4+i];
+ opImplicit.Body = new Block(statements = new StatementList(1));
+ val = new MemberBinding(new UnaryExpression(opImplicit.Parameters[0], NodeType.AddressOf), valueField);
+ val = new BinaryExpression(val, new Literal(t, CoreSystemTypes.Type), NodeType.Castclass);
+ statements.Add(new Return(val));
+ }
+ //Routines to forward interface calls to embedded object
+ for (int i = 4+n, m = members.Count; i < m; i++){
+ Method meth = (Method)members[i];
+ Method imeth = (Method)this.interfaceMethodFor[meth.UniqueKey];
+ Interface iface = (Interface)imeth.DeclaringType;
+ statements = new StatementList(2);
+ ParameterList parameters = meth.Parameters;
+ int k = parameters == null ? 0 : parameters.Count;
+ ExpressionList arguments = new ExpressionList(k);
+ if (parameters != null)
+ for (int j = 0; j < k; j++) arguments.Add(parameters[j]);
+ Expression obj = new BinaryExpression(new MemberBinding(meth.ThisParameter, valueField), new Literal(iface, CoreSystemTypes.Type), NodeType.Castclass);
+ MethodCall mcall = new MethodCall(new MemberBinding(obj, imeth), arguments, NodeType.Callvirt);
+ mcall.Type = imeth.ReturnType;
+ statements.Add(new ExpressionStatement(mcall));
+ statements.Add(new Return());
+ meth.Body = new Block(statements);
+ }
+ }
+ }
+ public class TypeUnion : Struct{
+ private TypeNodeList types; //sorted by UniqueKey
+ public TypeNodeList Types{
+ get{
+ if (this.types != null) return this.types;
+ if (this.ProvideTypeMembers != null) { MemberList mems = this.Members; if (mems != null) mems = null; }
+ return this.types;
+ }
+ set{
+ this.types = value;
+ }
+ }
+
+ private TypeUnion(TypeNodeList types, Identifier tName){
+ this.NodeType = NodeType.TypeUnion;
+ this.Flags = TypeFlags.Public|TypeFlags.Sealed;
+ this.Namespace = StandardIds.StructuralTypes;
+ this.Name = tName;
+ this.Types = types;
+ this.Interfaces = new InterfaceList(SystemTypes.TypeUnion);
+ this.isNormalized = true;
+ }
+ internal TypeUnion(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
+ : base(provideNestedTypes, provideAttributes, provideMembers, handle) {
+ this.NodeType = NodeType.TypeUnion;
+ this.typeCode = ElementType.ValueType;
+ }
+
+ internal static string/*!*/ BuildName(TypeNodeList types, string separator, ref TypeFlags visibility) {
+ int n = types == null ? 0 : types.Count;
+ if (n == 0) return "EmtpyUnion";
+ StringBuilder sb = new StringBuilder();
+ if (types != null)
+ for (int i = 0; i < n; i++){
+ TypeNode t = types[i];
+ if (t == null) continue;
+ visibility = TypeNode.GetVisibilityIntersection(visibility, t.Flags & TypeFlags.VisibilityMask);
+ sb.Append(t.Name.ToString());
+ if (i < n-1) sb.Append(separator);
+ }
+ return sb.ToString();
+ }
+ public static bool AreNormalized(TypeNodeList/*!*/ types) {
+ int id = 0;
+ for (int i = 0, n = types.Count; i < n; i++){
+ TypeNode type = types[i];
+ if (type == null) continue;
+ if (type.UniqueKey <= id || type is TypeUnion) return false;
+ id = type.UniqueKey;
+ }
+ return true;
+ }
+ public static TypeNodeList/*!*/ Normalize(TypeNodeList/*!*/ types) {
+ if (types.Count == 0) return types;
+ Hashtable ht = new Hashtable();
+ for (int i = 0, n = types.Count; i < n; i++){
+ TypeNode type = types[i];
+ if (type == null) continue; // error already reported.
+ TypeUnion tu = type as TypeUnion;
+ if (tu != null){
+ for (int ti = 0, tn = tu.Types.Count; ti < tn; ti++){
+ type = tu.Types[ti];
+ ht[type.UniqueKey] = type;
+ }
+ }else{
+ ht[type.UniqueKey] = type;
+ }
+ }
+ SortedList list = new SortedList(ht);
+ TypeNodeList result = new TypeNodeList(list.Count);
+ foreach (TypeNode t in list.Values)
+ result.Add(t);
+ return result;
+ }
+ public static TypeUnion For(TypeNodeList types, Module module) {
+ if (module == null) return null;
+ if (types != null && !TypeUnion.AreNormalized(types))
+ types = TypeUnion.Normalize(types);
+ TypeFlags visibility = TypeFlags.Public;
+ string name = TypeUnion.BuildName(types, "Or", ref visibility);
+ Identifier tName = Identifier.For(name);
+ int tCount = 0;
+ TypeUnion result = null;
+ TypeNode t = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, tName);
+ while (t != null){
+ //Mangled name is the same. But mangling is not unique, so check for equality.
+ TypeUnion tu = t as TypeUnion;
+ if (tu != null){
+ TypeNodeList ts = tu.Types;
+ int n = types == null ? 0 : types.Count;
+ bool goodMatch = ts != null && ts.Count == n;
+ for (int i = 0; goodMatch && i < n; i++) {
+ //^ assert types != null && ts != null;
+ goodMatch = types[i] == ts[i];
+ }
+ if (goodMatch) return tu;
+ }
+ //Mangle some more
+ tName = Identifier.For(name+(++tCount).ToString());
+ t = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, tName);
+ }
+ result = new TypeUnion(types, tName);
+ result.DeclaringModule = module;
+ module.Types.Add(result);
+ module.StructurallyEquivalentType[tName.UniqueIdKey] = result;
+ return result;
+ }
+ public static TypeUnion For(TypeNodeList/*!*/ types, TypeNode/*!*/ referringType) {
+ Module module = referringType.DeclaringModule;
+ if (module == null) return null;
+ if (!TypeUnion.AreNormalized(types))
+ types = TypeUnion.Normalize(types);
+ TypeFlags visibility = TypeFlags.Public;
+ string name = TypeUnion.BuildName(types, "Or", ref visibility);
+ Identifier tName = Identifier.For(name);
+ int tCount = 0;
+ TypeUnion result = null;
+ TypeNode t = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, tName);
+ while (t != null){
+ //Mangled name is the same. But mangling is not unique, so check for equality.
+ TypeUnion tu = t as TypeUnion;
+ if (tu != null){
+ TypeNodeList ts = tu.Types;
+ int n = types.Count;
+ bool goodMatch = ts != null && ts.Count == n;
+ for (int i = 0; goodMatch && i < n; i++) {
+ //^ assert ts != null;
+ goodMatch = types[i] == ts[i];
+ }
+ if (goodMatch) return tu;
+ }
+ //Mangle some more
+ tName = Identifier.For(name+(++tCount).ToString());
+ t = module.GetStructurallyEquivalentType(StandardIds.StructuralTypes, tName);
+ }
+ result = new TypeUnion(types, tName);
+ result.DeclaringModule = module;
+ switch (visibility){
+ case TypeFlags.NestedFamANDAssem:
+ case TypeFlags.NestedFamily:
+ case TypeFlags.NestedPrivate:
+ referringType.Members.Add(result);
+ result.DeclaringType = referringType;
+ result.Flags &= ~TypeFlags.VisibilityMask;
+ result.Flags |= TypeFlags.NestedPrivate;
+ break;
+ default:
+ module.Types.Add(result);
+ break;
+ }
+ module.StructurallyEquivalentType[tName.UniqueIdKey] = result;
+ return result;
+ }
+ public override bool IsAssignableTo(TypeNode targetType){
+ return targetType == this || targetType == CoreSystemTypes.Object;
+ }
+ public override bool IsStructural{
+ get{return true;}
+ }
+ public override bool IsStructurallyEquivalentTo(TypeNode type){
+ if (type == null) return false;
+ if (this == type) return true;
+ TypeUnion t = type as TypeUnion;
+ if (t == null) return false;
+ return this.IsStructurallyEquivalentList(this.Types, t.Types);
+ }
+ protected TypeNodeList structuralElementTypes;
+ public override TypeNodeList StructuralElementTypes{
+ get{
+ TypeNodeList result = this.structuralElementTypes;
+ if (result != null) return result;
+ this.structuralElementTypes = result = new TypeNodeList(1);
+ TypeNodeList types = this.Types;
+ for (int i = 0, n = types == null ? 0 : types.Count; i < n; i++){
+ TypeNode t = types[i];
+ if (t == null) continue;
+ result.Add(t);
+ }
+ return result;
+ }
+ }
+ protected TypeUnion unlabeledUnion = null;
+ public virtual TypeUnion UnlabeledUnion{
+ get{
+ TypeUnion result = this.unlabeledUnion;
+ if (result != null) return result;
+ if (this.Types == null) return this.unlabeledUnion = this;
+ TypeNodeList types = this.Types.Clone();
+ bool noChange = true;
+ for (int i = 0, n = types.Count; i < n; i++){
+ TupleType tup = types[i] as TupleType;
+ if (tup != null && tup.Members != null && tup.Members.Count == 3 && tup.Members[0] is Field){
+ types[i] = ((Field)tup.Members[0]).Type;
+ noChange = false;
+ }
+ }
+ if (noChange)
+ return this.unlabeledUnion = this;
+ else
+ return this.unlabeledUnion = new TypeUnion(types, Identifier.Empty);
+ }
+ }
+ public override MemberList Members{
+ get{
+ MemberList members = this.members;
+ if (members == null || this.membersBeingPopulated){
+ if (this.ProvideTypeMembers != null){
+ lock(this){
+ if (this.members != null) return this.members;
+ members = base.Members;
+ MemberList coercions = this.ExplicitCoercionMethods;
+ int n = coercions == null ? 0 : coercions.Count;
+ TypeNodeList typeList = this.Types = new TypeNodeList(n);
+ for (int i = 0; i < n; i++){
+ Method coercion = coercions[i] as Method;
+ if (coercion == null) continue;
+ typeList.Add(coercion.ReturnType);
+ }
+ return this.members;
+ }
+ }
+ members = this.Members = new MemberList();
+ //Value field
+ members.Add(new Field(this, null, FieldFlags.Private, StandardIds.Value, CoreSystemTypes.Object, null));
+ //Tag field
+ members.Add(new Field(this, null, FieldFlags.Private, StandardIds.Tag, CoreSystemTypes.UInt32, null));
+ //GetValue method (used to convert from subtype to supertype via FromObject on the superType)
+ ParameterList parameters = new ParameterList(0);
+ Method m = new Method(this, null, StandardIds.GetValue, parameters, CoreSystemTypes.Object, null);
+ m.Flags = MethodFlags.SpecialName|MethodFlags.Public; m.CallingConvention = CallingConventionFlags.HasThis;
+ members.Add(m);
+ //GetTag method (used in typeswitch)
+ parameters = new ParameterList(0);
+ m = new Method(this, null, StandardIds.GetTag, parameters, CoreSystemTypes.UInt32, null);
+ m.Flags = MethodFlags.SpecialName|MethodFlags.Public; m.CallingConvention = CallingConventionFlags.HasThis;
+ members.Add(m);
+ //GetTagAsType method (used to convert from subtype to supertype via FromObject on the superType)
+ parameters = new ParameterList(0);
+ m = new Method(this, null, StandardIds.GetTagAsType, parameters, CoreSystemTypes.Type, null);
+ m.Flags = MethodFlags.SpecialName|MethodFlags.Public; m.CallingConvention = CallingConventionFlags.HasThis;
+ members.Add(m);
+ //GetType
+ parameters = new ParameterList(0);
+ m = new Method(this, null, StandardIds.GetType, parameters, CoreSystemTypes.Type, null);
+ m.Flags = MethodFlags.Public; m.CallingConvention = CallingConventionFlags.HasThis;
+ members.Add(m);
+ //FromObject
+ parameters = new ParameterList(2);
+ parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.Value, CoreSystemTypes.Object, null, null));
+ parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.TagType, CoreSystemTypes.Type, null, null));
+ m = new Method(this, null, StandardIds.FromObject, parameters, this, null);
+ m.Flags = MethodFlags.Static|MethodFlags.SpecialName|MethodFlags.Public;
+ members.Add(m);
+ //coercion operators
+ TypeNodeList types = this.Types;
+ for (int i = 0, n = types.Count; i < n; i++){
+ TypeNode t = types[i];
+ parameters = new ParameterList(1);
+ parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.Value, t, null, null));
+ m = new Method(this, null, StandardIds.opImplicit, parameters, this, null);
+ m.Flags = MethodFlags.Static|MethodFlags.SpecialName|MethodFlags.Public;
+ members.Add(m);
+ parameters = new ParameterList(1);
+ parameters.Add(new Parameter(null, ParameterFlags.None, StandardIds.Value, this, null, null));
+ m = new Method(this, null, StandardIds.opExplicit, parameters, t, null);
+ m.Flags = MethodFlags.Static|MethodFlags.SpecialName|MethodFlags.Public;
+ members.Add(m);
+ }
+ this.ProvideBodiesForMethods();
+ }
+ return members;
+ }
+ set{
+ this.members = value;
+ }
+ }
+ public void ProvideBodiesForMethods(){
+ Method objectGetType = CoreSystemTypes.Object.GetMethod(StandardIds.GetType);
+ Method typeGetTypeFromHandle = (Method)CoreSystemTypes.Type.GetMembersNamed(Identifier.For("GetTypeFromHandle"))[0];
+ Method typeGetTypeHandle = (Method)CoreSystemTypes.Type.GetMembersNamed(Identifier.For("get_TypeHandle"))[0];
+ Method runtimeTypeHandleGetValue = (Method)CoreSystemTypes.RuntimeTypeHandle.GetMembersNamed(Identifier.For("get_Value"))[0];
+ if (objectGetType == null || typeGetTypeFromHandle == null || typeGetTypeHandle == null || runtimeTypeHandleGetValue == null) {
+ Debug.Fail(""); return;
+ }
+ MemberList members = this.members;
+ if (members == null) return;
+ Field valueField = (Field)members[0];
+ Field tagField = (Field)members[1];
+ //GetValue
+ Method getValueMethod = (Method)members[2];
+ StatementList statements = new StatementList(1);
+ statements.Add(new Return(new MemberBinding(getValueMethod.ThisParameter, valueField)));
+ getValueMethod.Body = new Block(statements);
+ //GetTag
+ Method getTagMethod = (Method)members[3];
+ statements = new StatementList(1);
+ statements.Add(new Return(new MemberBinding(getTagMethod.ThisParameter, tagField)));
+ getTagMethod.Body = new Block(statements);
+ //GetTagAsType
+ Method getTagAsTypeMethod = (Method)members[4];
+ TypeNodeList types = this.Types;
+ int n = types.Count;
+ Block returnBlock = new Block();
+ statements = new StatementList(n+4);
+ getTagAsTypeMethod.Body = new Block(statements);
+ BlockList targets = new BlockList(n);
+ SwitchInstruction sw = new SwitchInstruction(new MemberBinding(getTagAsTypeMethod.ThisParameter, tagField), targets);
+ statements.Add(sw);
+ //TODO: throw an exception
+ statements.Add(new ExpressionStatement(new UnaryExpression(new Literal(CoreSystemTypes.Object, CoreSystemTypes.Type), NodeType.Ldtoken)));
+ statements.Add(returnBlock);
+ for (int i = 0; i < n; i++){
+ TypeNode t = types[i];
+ StatementList ldToken = new StatementList(2);
+ ldToken.Add(new ExpressionStatement(new UnaryExpression(new Literal(t, CoreSystemTypes.Type), NodeType.Ldtoken)));
+ ldToken.Add(new Branch(null, returnBlock));
+ Block ldtokBlock = new Block(ldToken);
+ targets.Add(ldtokBlock);
+ statements.Add(ldtokBlock);
+ }
+ statements = returnBlock.Statements = new StatementList(1);
+ statements.Add(new Return(new MethodCall(new MemberBinding(null, typeGetTypeFromHandle), null)));
+ //GetType
+ Method getTypeMethod = (Method)members[5];
+ statements = new StatementList(4);
+ getTypeMethod.Body = new Block(statements);
+ MemberBinding mb = new MemberBinding(getTypeMethod.ThisParameter, valueField);
+ Local loc = new Local(CoreSystemTypes.Object);
+ statements.Add(new AssignmentStatement(loc, mb));
+ Block callGetTagAsType = new Block();
+ statements.Add(new Branch(new UnaryExpression(loc, NodeType.LogicalNot), callGetTagAsType));
+ statements.Add(new Return(new MethodCall(new MemberBinding(loc, objectGetType), null)));
+ statements.Add(callGetTagAsType);
+ statements.Add(new Return(new MethodCall(new MemberBinding(getTypeMethod.ThisParameter, getTagAsTypeMethod), null)));
+ //FromObject
+ Method fromObjectMethod = (Method)members[6];
+ fromObjectMethod.InitLocals = true;
+ statements = new StatementList(n+8); //TODO: get the right expression
+ fromObjectMethod.Body = new Block(statements);
+ MethodCall getTypeHandle = new MethodCall(new MemberBinding(fromObjectMethod.Parameters[1], typeGetTypeHandle), null, NodeType.Callvirt);
+ Local handle = new Local(Identifier.Empty, CoreSystemTypes.RuntimeTypeHandle);
+ statements.Add(new AssignmentStatement(handle, getTypeHandle));
+ MethodCall getValue = new MethodCall(new MemberBinding(new UnaryExpression(handle, NodeType.AddressOf), runtimeTypeHandleGetValue), null);
+ getValue.Type = CoreSystemTypes.UIntPtr;
+ statements.Add(new ExpressionStatement(getValue));
+ Local temp = new Local(Identifier.Empty, CoreSystemTypes.UInt32);
+ Local result = new Local(Identifier.Empty, this);
+ Expression dup = new Expression(NodeType.Dup);
+ Block next = new Block();
+ Block curr = new Block();
+ Block setTag = new Block();
+ for (int i = 0; i < n; i++){
+ TypeNode t = types[i];
+ StatementList stats = curr.Statements = new StatementList(4);
+ UnaryExpression ldtok = new UnaryExpression(new Literal(t, CoreSystemTypes.Type), NodeType.Ldtoken);
+ stats.Add(new AssignmentStatement(handle, ldtok));
+ getValue = new MethodCall(new MemberBinding(new UnaryExpression(handle, NodeType.AddressOf), runtimeTypeHandleGetValue), null);
+ Expression compare = new BinaryExpression(dup, getValue, NodeType.Eq);
+ stats.Add(new Branch(compare, next));
+ stats.Add(new AssignmentStatement(temp, new Literal(i, CoreSystemTypes.UInt32)));
+ if (i < n-1)
+ stats.Add(new Branch(null, setTag));
+ statements.Add(curr);
+ curr = next;
+ next = new Block();
+ }
+ statements.Add(curr);
+ statements.Add(setTag);
+ statements.Add(new ExpressionStatement(new UnaryExpression(null, NodeType.Pop)));
+ Expression resultAddr = new UnaryExpression(result, NodeType.AddressOf);
+ statements.Add(new AssignmentStatement(new MemberBinding(resultAddr, tagField), temp));
+ statements.Add(new AssignmentStatement(new MemberBinding(resultAddr, valueField), fromObjectMethod.Parameters[0]));
+ statements.Add(new Return(result));
+ for (int i = 0; i < n; i++){
+ TypeNode t = types[i];
+ if (t == null) continue;
+ bool isValueType = t.IsValueType;
+ MemberBinding tExpr = new MemberBinding(null, t);
+ Method opImplicit = (Method)members[7+i*2];
+ opImplicit.Body = new Block(statements = new StatementList(3));
+ statements.Add(new AssignmentStatement(new MemberBinding(resultAddr, tagField), new Literal(i, CoreSystemTypes.UInt32)));
+ Parameter p0 = opImplicit.Parameters[0];
+ p0.Type = t;
+ Expression val = p0;
+ if (isValueType) val = new BinaryExpression(val, tExpr, NodeType.Box, CoreSystemTypes.Object);
+ statements.Add(new AssignmentStatement(new MemberBinding(resultAddr, valueField), val));
+ statements.Add(new Return(result));
+ Method opExplicit = (Method)members[8+i*2];
+ opExplicit.ReturnType = t;
+ opExplicit.Body = new Block(statements = new StatementList(1));
+ Expression loadValue = new MemberBinding(new UnaryExpression(opExplicit.Parameters[0], NodeType.AddressOf), valueField);
+ if (isValueType)
+ val = new AddressDereference(new BinaryExpression(loadValue, tExpr, NodeType.Unbox), t);
+ else
+ val = new BinaryExpression(loadValue, tExpr, NodeType.Castclass);
+ statements.Add(new Return(val));
+ }
+ }
+ }
+ /// <summary>
+ /// Bundles a type with a boolean expression. The bundle is a subtype of the given type.
+ /// The class is a struct with a single private field of the given type and implicit coercions to and from the underlying type.
+ /// The to coercion checks that the constraint is satisfied and throws ArgumentOutOfRangeException if not.
+ /// </summary>
+ public class ConstrainedType : Struct{
+ protected TypeNode underlyingType;
+ public TypeNode UnderlyingTypeExpression;
+ public Expression Constraint;
+ public ConstrainedType(TypeNode/*!*/ underlyingType, Expression/*!*/ constraint) {
+ this.NodeType = NodeType.ConstrainedType;
+ this.underlyingType = underlyingType;
+ this.Flags = TypeFlags.Public|TypeFlags.Sealed|TypeFlags.SpecialName;
+ this.Constraint = constraint;
+ this.Namespace = StandardIds.StructuralTypes;
+ this.Name = Identifier.For("Constrained type:"+base.UniqueKey);
+ this.Interfaces = new InterfaceList(SystemTypes.ConstrainedType);
+ }
+ public ConstrainedType(TypeNode/*!*/ underlyingType, Expression/*!*/ constraint, TypeNode/*!*/ declaringType) {
+ this.NodeType = NodeType.ConstrainedType;
+ this.underlyingType = underlyingType;
+ this.Flags = TypeFlags.NestedPublic|TypeFlags.Sealed|TypeFlags.SpecialName;
+ this.Constraint = constraint;
+ this.Namespace = StandardIds.StructuralTypes;
+ this.Name = Identifier.For("Constrained type:"+base.UniqueKey);
+ this.Interfaces = new InterfaceList(SystemTypes.ConstrainedType);
+ this.DeclaringType = declaringType;
+ this.DeclaringModule = declaringType.DeclaringModule;
+ declaringType.Members.Add(this);
+ }
+ internal ConstrainedType(NestedTypeProvider provideNestedTypes, TypeAttributeProvider provideAttributes, TypeMemberProvider provideMembers, object handle)
+ : base(provideNestedTypes, provideAttributes, provideMembers, handle) {
+ this.NodeType = NodeType.ConstrainedType;
+ this.typeCode = ElementType.ValueType;
+ }
+ public override bool IsStructural{
+ get{return true;}
+ }
+ protected TypeNodeList structuralElementTypes;
+ public override TypeNodeList StructuralElementTypes{
+ get{
+ TypeNodeList result = this.structuralElementTypes;
+ if (result != null) return result;
+ this.structuralElementTypes = result = new TypeNodeList(1);
+ result.Add(this.UnderlyingType);
+ return result;
+ }
+ }
+ public virtual void ProvideMembers(){
+ MemberList members = this.members = new MemberList();
+ //Value field
+ Field valueField = new Field(this, null, FieldFlags.Assembly, StandardIds.Value, this.underlyingType, null);
+ members.Add(valueField);
+ //Implicit conversion from this type to underlying type
+ ParameterList parameters = new ParameterList(1);
+ Parameter valuePar = new Parameter(null, ParameterFlags.None, StandardIds.Value, this, null, null);
+ parameters.Add(valuePar);
+ Method toUnderlying = new Method(this, null, StandardIds.opImplicit, parameters, this.underlyingType, null);
+ toUnderlying.Flags = MethodFlags.Static|MethodFlags.SpecialName|MethodFlags.Public;
+ members.Add(toUnderlying);
+ //Implicit conversion from underlying type to this type
+ parameters = new ParameterList(1);
+ parameters.Add(valuePar = new Parameter(null, ParameterFlags.None, StandardIds.Value, this.underlyingType, null, null));
+ Method fromUnderlying = new Method(this, null, StandardIds.opImplicit, parameters, this, null);
+ fromUnderlying.Flags = MethodFlags.Static|MethodFlags.SpecialName|MethodFlags.Public;
+ members.Add(fromUnderlying);
+ this.AddCoercionWrappers(this.UnderlyingType.ExplicitCoercionMethods, StandardIds.opExplicit, fromUnderlying, toUnderlying);
+ this.AddCoercionWrappers(this.UnderlyingType.ImplicitCoercionMethods, StandardIds.opImplicit, fromUnderlying, toUnderlying);
+ }
+ private void AddCoercionWrappers(MemberList/*!*/ coercions, Identifier/*!*/ id, Method/*!*/ fromUnderlying, Method/*!*/ toUnderlying) {
+ MemberList members = this.members;
+ for (int i = 0, n = coercions.Count; i < n; i++){
+ Method coercion = coercions[i] as Method;
+ if (coercion == null || coercion.Parameters == null || coercion.Parameters.Count != 1) continue;
+ ParameterList parameters = new ParameterList(1);
+ Parameter valuePar = new Parameter(null, ParameterFlags.None, StandardIds.Value, null, null, null);
+ parameters.Add(valuePar);
+ Method m = new Method(this, null, id, parameters, null, null);
+ m.Flags = MethodFlags.Static|MethodFlags.SpecialName|MethodFlags.Public;
+ Expression arg = valuePar;
+ MethodCall call = new MethodCall(new MemberBinding(null, coercion), new ExpressionList(arg));
+ if (coercion.ReturnType == this.UnderlyingType){
+ m.ReturnType = this;
+ valuePar.Type = coercion.Parameters[0].Type;
+ call = new MethodCall(new MemberBinding(null, fromUnderlying), new ExpressionList(call));
+ }else{
+ m.ReturnType = coercion.ReturnType;
+ valuePar.Type = this;
+ call.Operands[0] = new MethodCall(new MemberBinding(null, toUnderlying), new ExpressionList(arg));
+ }
+ m.Body = new Block(new StatementList(new Return(call)));
+ members.Add(m);
+ }
+ }
+ public void ProvideBodiesForMethods(){
+ MemberList members = this.members;
+ if (members == null) return;
+ Field valueField = (Field)members[0];
+ //Implicit conversion from this type to underlying type
+ Method toUnderlying = (Method)members[1];
+ Parameter valuePar = toUnderlying.Parameters[0];
+ StatementList statements = new StatementList(1);
+ statements.Add(new Return(new MemberBinding(new UnaryExpression(valuePar, NodeType.AddressOf), valueField)));
+ toUnderlying.Body = new Block(statements);
+ //Implicit conversion from underlying type to this type
+ Method fromUnderlying = (Method)members[2];
+ valuePar = fromUnderlying.Parameters[0];
+ statements = new StatementList(4);
+ fromUnderlying.Body = new Block(statements);
+ Block succeed = new Block();
+ Local temp = new Local(Identifier.Empty, this);
+ statements.Add(new Branch(this.Constraint, succeed));
+ InstanceInitializer constr = SystemTypes.ArgumentOutOfRangeException.GetConstructor();
+ if (constr == null) { Debug.Fail(""); return; }
+ MemberBinding argException = new MemberBinding(null, constr);
+ statements.Add(new Throw(new Construct(argException, null)));
+ statements.Add(succeed);
+ statements.Add(new AssignmentStatement(new MemberBinding(new UnaryExpression(temp, NodeType.AddressOf), valueField), valuePar));
+ statements.Add(new Return(temp));
+ }
+ public TypeNode UnderlyingType{
+ get{
+ TypeNode underlyingType = this.underlyingType;
+ if (underlyingType == null){
+ Field f = this.GetField(StandardIds.Value);
+ if (f != null)
+ this.underlyingType = underlyingType = f.Type;
+ }
+ return underlyingType;
+ }
+ set{
+ this.underlyingType = value;
+ }
+ }
+ }
+#endif
+ public abstract class TypeModifier : TypeNode
+ {
+ private TypeNode/*!*/ modifier;
+ private TypeNode/*!*/ modifiedType;
+#if !MinimalReader
+ public TypeNode ModifierExpression;
+ public TypeNode ModifiedTypeExpression;
+#endif
+ internal TypeModifier(NodeType type, TypeNode/*!*/ modifier, TypeNode/*!*/ modified)
+ : base(type)
+ {
+ this.modifier = modifier;
+ this.modifiedType = modified;
+ this.DeclaringModule = modified.DeclaringModule;
+ this.Namespace = modified.Namespace;
+ if (type == NodeType.OptionalModifier)
+ {
+ this.typeCode = ElementType.OptionalModifier;
+ this.Name = Identifier.For("optional(" + modifier.Name + ") " + modified.Name);
+ this.fullName = "optional(" + modifier.FullName + ") " + modified.FullName;
+ }
+ else
+ {
+ this.typeCode = ElementType.RequiredModifier;
+ this.Name = Identifier.For("required(" + modifier.Name + ") " + modified.Name);
+ this.fullName = "required(" + modifier.FullName + ") " + modified.FullName;
+ }
+ this.Flags = modified.Flags;
+ }
+ public TypeNode/*!*/ Modifier
+ {
+ get { return this.modifier; }
+ set { this.modifier = value; }
+ }
+ public TypeNode/*!*/ ModifiedType
+ {
+ get { return this.modifiedType; }
+ set { this.modifiedType = value; }
+ }
+ public override Node/*!*/ Clone()
+ {
+ Debug.Assert(false);
+ return base.Clone();
+ }
+ public override string GetFullUnmangledNameWithoutTypeParameters()
+ {
+ return this.ModifiedType.GetFullUnmangledNameWithoutTypeParameters();
+ }
+ public override string GetFullUnmangledNameWithTypeParameters()
+ {
+ return this.ModifiedType.GetFullUnmangledNameWithTypeParameters();
+ }
+ public override string/*!*/ GetUnmangledNameWithoutTypeParameters()
+ {
+ return this.ModifiedType.GetUnmangledNameWithoutTypeParameters();
+ }
+ public override bool IsUnmanaged
+ {
+ get { return this.ModifiedType.IsUnmanaged; }
+ }
+ public override bool IsStructural
+ {
+ get { return true; }
+ }
+ public override bool IsStructurallyEquivalentTo(TypeNode type)
+ {
+ if (type == null) return false;
+ if (this == type) return true;
+ if (this.NodeType != type.NodeType) return false;
+ TypeModifier t = type as TypeModifier;
+ if (t == null) { Debug.Assert(false); return false; }
+ if (this.Modifier != t.Modifier && (this.Modifier == null || !this.Modifier.IsStructurallyEquivalentTo(t.Modifier)))
+ return false;
+ if (this.ModifiedType != t.ModifiedType && (this.ModifiedType == null || !this.ModifiedType.IsStructurallyEquivalentTo(t.ModifiedType)))
+ return false;
+ return true;
+ }
+ public override bool IsValueType
+ {
+ get
+ {
+ return this.ModifiedType.IsValueType;
+ }
+ }
+
+ public override bool IsPointerType
+ {
+ get
+ {
+ return this.ModifiedType.IsPointerType;
+ }
+ }
+
+#if ExtendedRuntime
+ public override bool IsReferenceType {
+ get {
+ return this.ModifiedType.IsReferenceType;
+ }
+ }
+#endif
+
+ public override bool IsTemplateParameter
+ {
+ get
+ {
+ return this.ModifiedType.IsTemplateParameter;
+ }
+ }
+ protected TypeNodeList structuralElementTypes;
+ public override TypeNodeList StructuralElementTypes
+ {
+ get
+ {
+ TypeNodeList result = this.structuralElementTypes;
+ if (result != null) return result;
+ this.structuralElementTypes = result = new TypeNodeList(2);
+ result.Add(this.ModifiedType);
+ result.Add(this.Modifier);
+ return result;
+ }
+ }
+#if FxCop
+ internal override void GetName(TypeFormat options, StringBuilder name)
+ {
+ if (options.ShowTypeModifiers)
+ {
+ base.GetName(options, name);
+ return;
+ }
+ this.modifiedType.GetName(options, name);
+ }
+#endif
+ }
+ public class OptionalModifier : TypeModifier
+ {
+ internal OptionalModifier(TypeNode/*!*/ modifier, TypeNode/*!*/ modified)
+ : base(NodeType.OptionalModifier, modifier, modified)
+ {
+ }
+ public static OptionalModifier/*!*/ For(TypeNode/*!*/ modifier, TypeNode/*!*/ modified)
+ {
+ return (OptionalModifier)modified.GetModified(modifier, true);
+ }
+#if !NoXml
+ internal override void AppendDocumentIdMangledName(StringBuilder/*!*/ sb, TypeNodeList methodTypeParameters, TypeNodeList typeParameters)
+ {
+ this.ModifiedType.AppendDocumentIdMangledName(sb, methodTypeParameters, typeParameters);
+ sb.Append('!');
+ this.Modifier.AppendDocumentIdMangledName(sb, methodTypeParameters, typeParameters);
+ }
+#endif
+ }
+ public class RequiredModifier : TypeModifier
+ {
+ internal RequiredModifier(TypeNode/*!*/ modifier, TypeNode/*!*/ modified)
+ : base(NodeType.RequiredModifier, modifier, modified)
+ {
+ }
+ public static RequiredModifier/*!*/ For(TypeNode/*!*/ modifier, TypeNode/*!*/ modified)
+ {
+ return (RequiredModifier)modified.GetModified(modifier, false);
+ }
+#if !NoXml
+ internal override void AppendDocumentIdMangledName(StringBuilder/*!*/ sb, TypeNodeList methodTypeParameters, TypeNodeList typeParameters)
+ {
+ this.ModifiedType.AppendDocumentIdMangledName(sb, methodTypeParameters, typeParameters);
+ sb.Append('|');
+ this.Modifier.AppendDocumentIdMangledName(sb, methodTypeParameters, typeParameters);
+ }
+#endif
+ }
+#if !MinimalReader
+ public class OptionalModifierTypeExpression : TypeNode, ISymbolicTypeReference
+ {
+ public TypeNode ModifiedType;
+ public TypeNode Modifier;
+
+ public OptionalModifierTypeExpression(TypeNode elementType, TypeNode modifier)
+ : base(NodeType.OptionalModifierTypeExpression)
+ {
+ this.ModifiedType = elementType;
+ this.Modifier = modifier;
+ }
+ public OptionalModifierTypeExpression(TypeNode elementType, TypeNode modifier, SourceContext sctx)
+ : this(elementType, modifier)
+ {
+ this.SourceContext = sctx;
+ }
+ /// <summary>
+ /// Only needed because IsUnmanaged test is performed in the Looker rather than checker. Once the test
+ /// is moved, this code can be removed.
+ /// </summary>
+ public override bool IsUnmanaged
+ {
+ get
+ {
+ return this.ModifiedType == null ? false : this.ModifiedType.IsUnmanaged;
+ }
+ }
+
+ }
+ public class RequiredModifierTypeExpression : TypeNode, ISymbolicTypeReference
+ {
+ public TypeNode ModifiedType;
+ public TypeNode Modifier;
+
+ public RequiredModifierTypeExpression(TypeNode elementType, TypeNode modifier)
+ : base(NodeType.RequiredModifierTypeExpression)
+ {
+ this.ModifiedType = elementType;
+ this.Modifier = modifier;
+ }
+ public RequiredModifierTypeExpression(TypeNode elementType, TypeNode modifier, SourceContext sctx)
+ : this(elementType, modifier)
+ {
+ this.SourceContext = sctx;
+ }
+ /// <summary>
+ /// Can be removed once the Unmanaged check moves from Looker to Checker.
+ /// </summary>
+ public override bool IsUnmanaged
+ {
+ get
+ {
+ return this.ModifiedType == null ? false : this.ModifiedType.IsUnmanaged;
+ }
+ }
+
+ }
+#endif
+ public class FunctionPointer : TypeNode
+ {
+ internal FunctionPointer(TypeNodeList parameterTypes, TypeNode/*!*/ returnType, Identifier name)
+ : base(NodeType.FunctionPointer)
+ {
+ this.Name = name;
+ this.Namespace = returnType.Namespace;
+ this.parameterTypes = parameterTypes;
+ this.returnType = returnType;
+ this.typeCode = ElementType.FunctionPointer;
+ this.varArgStart = int.MaxValue;
+ }
+ private CallingConventionFlags callingConvention;
+ public CallingConventionFlags CallingConvention
+ {
+ get { return this.callingConvention; }
+ set { this.callingConvention = value; }
+ }
+ private TypeNodeList parameterTypes;
+ public TypeNodeList ParameterTypes
+ {
+ get { return this.parameterTypes; }
+ set { this.parameterTypes = value; }
+ }
+ private TypeNode returnType;
+ public TypeNode ReturnType
+ {
+ get { return this.returnType; }
+ set { this.returnType = value; }
+ }
+ private int varArgStart;
+ public int VarArgStart
+ {
+ get { return this.varArgStart; }
+ set { this.varArgStart = value; }
+ }
+ public override bool IsStatic
+ {
+ get { return (this.CallingConvention & CallingConventionFlags.HasThis) == 0; }
+ }
+ public override bool IsStructural
+ {
+ get { return true; }
+ }
+ protected TypeNodeList structuralElementTypes;
+ public override TypeNodeList StructuralElementTypes
+ {
+ get
+ {
+ TypeNodeList result = this.structuralElementTypes;
+ if (result != null) return result;
+ this.structuralElementTypes = result = new TypeNodeList();
+ result.Add(this.ReturnType);
+ TypeNodeList ptypes = this.ParameterTypes;
+ for (int i = 0, n = ptypes == null ? 0 : ptypes.Count; i < n; i++)
+ {
+ TypeNode ptype = ptypes[i];
+ if (ptype == null) continue;
+ result.Add(ptype);
+ }
+ return result;
+ }
+ }
+ public override bool IsStructurallyEquivalentTo(TypeNode type)
+ {
+ if (type == null) return false;
+ if (this == type) return true;
+ FunctionPointer t = type as FunctionPointer;
+ if (t == null) return false;
+ if (this.Flags != t.Flags || this.CallingConvention != t.CallingConvention || this.VarArgStart != t.VarArgStart) return false;
+ if (this.ReturnType == null || t.ReturnType == null) return false;
+ if (this.ReturnType != t.ReturnType && !this.ReturnType.IsStructurallyEquivalentTo(t.ReturnType)) return false;
+ return this.IsStructurallyEquivalentList(this.ParameterTypes, t.ParameterTypes);
+ }
+ public static FunctionPointer/*!*/ For(TypeNodeList/*!*/ parameterTypes, TypeNode/*!*/ returnType)
+ {
+ Module mod = returnType.DeclaringModule;
+ if (mod == null) { Debug.Fail(""); mod = new Module(); }
+ StringBuilder sb = new StringBuilder("function pointer ");
+ sb.Append(returnType.FullName);
+ sb.Append('(');
+ for (int i = 0, n = parameterTypes == null ? 0 : parameterTypes.Count; i < n; i++)
+ {
+ TypeNode type = parameterTypes[i];
+ if (type == null) continue;
+ if (i != 0) sb.Append(',');
+ sb.Append(type.FullName);
+ }
+ sb.Append(')');
+ Identifier name = Identifier.For(sb.ToString());
+ TypeNode t = mod.GetStructurallyEquivalentType(returnType.Namespace, name);
+ int counter = 1;
+ while (t != null)
+ {
+ FunctionPointer fp = t as FunctionPointer;
+ if (fp != null)
+ {
+ if (fp.ReturnType == returnType && FunctionPointer.ParameterTypesAreEquivalent(fp.ParameterTypes, parameterTypes))
+ return fp;
+ }
+ name = Identifier.For(name.ToString() + counter++);
+ t = mod.GetStructurallyEquivalentType(returnType.Namespace, name);
+ }
+ FunctionPointer result = t as FunctionPointer;
+ if (result == null)
+ {
+ result = new FunctionPointer(parameterTypes, returnType, name);
+ result.DeclaringModule = mod;
+ mod.StructurallyEquivalentType[name.UniqueIdKey] = result;
+ }
+ return result;
+ }
+ private static bool ParameterTypesAreEquivalent(TypeNodeList list1, TypeNodeList list2)
+ {
+ if (list1 == null || list2 == null) return list1 == list2;
+ int n = list1.Count;
+ if (n != list2.Count) return false;
+ for (int i = 0; i < n; i++)
+ if (list1[i] != list2[i]) return false;
+ return true;
+ }
+ }
+ public interface ISymbolicTypeReference
+ {
+ }
+#if !MinimalReader
+ public class ArrayTypeExpression : ArrayType, ISymbolicTypeReference
+ {
+ //TODO: add expressions for elementType, rank, sizes and lowerbounds
+ public bool LowerBoundIsUnknown;
+ public ArrayTypeExpression()
+ : base()
+ {
+ this.NodeType = NodeType.ArrayTypeExpression;
+ }
+ public ArrayTypeExpression(TypeNode/*!*/ elementType, int rank)
+ : base(elementType, rank)
+ {
+ this.NodeType = NodeType.ArrayTypeExpression;
+ }
+ public ArrayTypeExpression(TypeNode/*!*/ elementType, int rank, int[] sizes)
+ : base(elementType, rank, sizes)
+ {
+ this.NodeType = NodeType.ArrayTypeExpression;
+ }
+ public ArrayTypeExpression(TypeNode/*!*/ elementType, int rank, int[] sizes, int[] lowerBounds)
+ : base(elementType, rank, sizes, sizes)
+ {
+ this.NodeType = NodeType.ArrayTypeExpression;
+ }
+ public ArrayTypeExpression(TypeNode/*!*/ elementType, int rank, SourceContext sctx)
+ : base(elementType, rank)
+ {
+ this.NodeType = NodeType.ArrayTypeExpression;
+ this.SourceContext = sctx;
+ }
+ public ArrayTypeExpression(TypeNode/*!*/ elementType, int rank, int[] sizes, SourceContext sctx)
+ : base(elementType, rank, sizes)
+ {
+ this.NodeType = NodeType.ArrayTypeExpression;
+ this.SourceContext = sctx;
+ }
+ public ArrayTypeExpression(TypeNode/*!*/ elementType, int rank, int[] sizes, int[] lowerBounds, SourceContext sctx)
+ : base(elementType, rank, sizes, sizes)
+ {
+ this.NodeType = NodeType.ArrayTypeExpression;
+ this.SourceContext = sctx;
+ }
+ }
+ public class ClassExpression : Class, ISymbolicTypeReference
+ {
+ public Expression Expression;
+
+ public ClassExpression(Expression expression)
+ {
+ this.NodeType = NodeType.ClassExpression;
+ this.Expression = expression;
+ }
+ public ClassExpression(Expression expression, TypeNodeList templateArguments)
+ {
+ this.NodeType = NodeType.ClassExpression;
+ this.Expression = expression;
+ this.TemplateArguments = templateArguments;
+ if (templateArguments != null) this.TemplateArgumentExpressions = templateArguments.Clone();
+ }
+ public ClassExpression(Expression expression, SourceContext sctx)
+ {
+ this.NodeType = NodeType.ClassExpression;
+ this.Expression = expression;
+ this.SourceContext = sctx;
+ }
+ public ClassExpression(Expression expression, TypeNodeList templateArguments, SourceContext sctx)
+ {
+ this.NodeType = NodeType.ClassExpression;
+ this.Expression = expression;
+ this.TemplateArguments = this.TemplateArgumentExpressions = templateArguments;
+ if (templateArguments != null) this.TemplateArgumentExpressions = templateArguments.Clone();
+ this.SourceContext = sctx;
+ }
+ }
+#endif
+ public class InterfaceExpression : Interface, ISymbolicTypeReference
+ {
+ private Expression expression;
+ public InterfaceExpression(Expression expression)
+ : base(null)
+ {
+ this.NodeType = NodeType.InterfaceExpression;
+ this.Expression = expression;
+ }
+#if !MinimalReader
+ public InterfaceExpression(Expression expression, SourceContext sctx)
+ : base(null)
+ {
+ this.NodeType = NodeType.InterfaceExpression;
+ this.Expression = expression;
+ this.SourceContext = sctx;
+ }
+#endif
+ public Expression Expression
+ {
+ get { return this.expression; }
+ set { this.expression = value; }
+ }
+ }
+#if !MinimalReader
+ public class FlexArrayTypeExpression : TypeNode, ISymbolicTypeReference
+ {
+ public TypeNode ElementType;
+ public FlexArrayTypeExpression(TypeNode elementType)
+ : base(NodeType.FlexArrayTypeExpression)
+ {
+ this.ElementType = elementType;
+ }
+ public FlexArrayTypeExpression(TypeNode elementType, SourceContext sctx)
+ : base(NodeType.FlexArrayTypeExpression)
+ {
+ this.ElementType = elementType;
+ this.SourceContext = sctx;
+ }
+ }
+ public class FunctionTypeExpression : TypeNode, ISymbolicTypeReference
+ {
+ public ParameterList Parameters;
+ public TypeNode ReturnType;
+ public FunctionTypeExpression(TypeNode returnType, ParameterList parameters)
+ : base(NodeType.FunctionTypeExpression)
+ {
+ this.ReturnType = returnType;
+ this.Parameters = parameters;
+ }
+ public FunctionTypeExpression(TypeNode returnType, ParameterList parameters, SourceContext sctx)
+ : base(NodeType.FunctionTypeExpression)
+ {
+ this.ReturnType = returnType;
+ this.Parameters = parameters;
+ this.SourceContext = sctx;
+ }
+ }
+ public class PointerTypeExpression : Pointer, ISymbolicTypeReference
+ {
+ public PointerTypeExpression(TypeNode/*!*/ elementType)
+ : base(elementType)
+ {
+ this.NodeType = NodeType.PointerTypeExpression;
+ }
+ public PointerTypeExpression(TypeNode/*!*/ elementType, SourceContext sctx)
+ : base(elementType)
+ {
+ this.NodeType = NodeType.PointerTypeExpression;
+ this.SourceContext = sctx;
+ }
+ /// <summary>
+ /// This is only needed because the Unmanaged test is done in the Looker rather than the checker.
+ /// (Once the check moves, this can be removed).
+ /// </summary>
+ public override bool IsUnmanaged
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ }
+ public class ReferenceTypeExpression : Reference, ISymbolicTypeReference
+ {
+ public ReferenceTypeExpression(TypeNode/*!*/ elementType)
+ : base(elementType)
+ {
+ this.NodeType = NodeType.ReferenceTypeExpression;
+ }
+ public ReferenceTypeExpression(TypeNode/*!*/ elementType, SourceContext sctx)
+ : base(elementType)
+ {
+ this.NodeType = NodeType.ReferenceTypeExpression;
+ this.SourceContext = sctx;
+ }
+ }
+ public class StreamTypeExpression : TypeNode, ISymbolicTypeReference
+ {
+ public TypeNode ElementType;
+ public StreamTypeExpression(TypeNode elementType)
+ : base(NodeType.StreamTypeExpression)
+ {
+ this.ElementType = elementType;
+ }
+ public StreamTypeExpression(TypeNode elementType, SourceContext sctx)
+ : base(NodeType.StreamTypeExpression)
+ {
+ this.ElementType = elementType;
+ this.SourceContext = sctx;
+ }
+ }
+ public class NonEmptyStreamTypeExpression : TypeNode, ISymbolicTypeReference
+ {
+ public TypeNode ElementType;
+ public NonEmptyStreamTypeExpression(TypeNode elementType)
+ : base(NodeType.NonEmptyStreamTypeExpression)
+ {
+ this.ElementType = elementType;
+ }
+ public NonEmptyStreamTypeExpression(TypeNode elementType, SourceContext sctx)
+ : base(NodeType.NonEmptyStreamTypeExpression)
+ {
+ this.ElementType = elementType;
+ this.SourceContext = sctx;
+ }
+ }
+ public class BoxedTypeExpression : TypeNode, ISymbolicTypeReference
+ {
+ public TypeNode ElementType;
+ public BoxedTypeExpression(TypeNode elementType)
+ : base(NodeType.BoxedTypeExpression)
+ {
+ this.ElementType = elementType;
+ }
+ public BoxedTypeExpression(TypeNode elementType, SourceContext sctx)
+ : base(NodeType.BoxedTypeExpression)
+ {
+ this.ElementType = elementType;
+ this.SourceContext = sctx;
+ }
+ }
+ public class InvariantTypeExpression : TypeNode, ISymbolicTypeReference
+ {
+ public TypeNode ElementType;
+ public InvariantTypeExpression(TypeNode elementType)
+ : base(NodeType.InvariantTypeExpression)
+ {
+ this.ElementType = elementType;
+ }
+ public InvariantTypeExpression(TypeNode elementType, SourceContext sctx)
+ : base(NodeType.InvariantTypeExpression)
+ {
+ this.ElementType = elementType;
+ this.SourceContext = sctx;
+ }
+ }
+ public class NonNullTypeExpression : TypeNode, ISymbolicTypeReference
+ {
+ public TypeNode ElementType;
+ public NonNullTypeExpression(TypeNode elementType)
+ : base(NodeType.NonNullTypeExpression)
+ {
+ this.ElementType = elementType;
+ }
+ public NonNullTypeExpression(TypeNode elementType, SourceContext sctx)
+ : base(NodeType.NonNullTypeExpression)
+ {
+ this.ElementType = elementType;
+ this.SourceContext = sctx;
+ }
+ }
+ public class NonNullableTypeExpression : TypeNode, ISymbolicTypeReference
+ {
+ public TypeNode ElementType;
+ public NonNullableTypeExpression(TypeNode elementType)
+ : base(NodeType.NonNullableTypeExpression)
+ {
+ this.ElementType = elementType;
+ }
+ public NonNullableTypeExpression(TypeNode elementType, SourceContext sctx)
+ : base(NodeType.NonNullableTypeExpression)
+ {
+ this.ElementType = elementType;
+ this.SourceContext = sctx;
+ }
+ }
+ public class NullableTypeExpression : TypeNode, ISymbolicTypeReference
+ {
+ public TypeNode ElementType;
+ public NullableTypeExpression(TypeNode elementType)
+ : base(NodeType.NullableTypeExpression)
+ {
+ this.ElementType = elementType;
+ }
+ public NullableTypeExpression(TypeNode elementType, SourceContext sctx)
+ : base(NodeType.NullableTypeExpression)
+ {
+ this.ElementType = elementType;
+ this.SourceContext = sctx;
+ }
+ }
+ public class TupleTypeExpression : TypeNode, ISymbolicTypeReference
+ {
+ public FieldList Domains;
+ public TupleTypeExpression(FieldList domains)
+ : base(NodeType.TupleTypeExpression)
+ {
+ this.Domains = domains;
+ }
+ public TupleTypeExpression(FieldList domains, SourceContext sctx)
+ : base(NodeType.TupleTypeExpression)
+ {
+ this.Domains = domains;
+ this.SourceContext = sctx;
+ }
+ }
+ public class TypeIntersectionExpression : TypeNode, ISymbolicTypeReference
+ {
+ public TypeNodeList Types;
+ public TypeIntersectionExpression(TypeNodeList types)
+ : base(NodeType.TypeIntersectionExpression)
+ {
+ this.Types = types;
+ }
+ public TypeIntersectionExpression(TypeNodeList types, SourceContext sctx)
+ : base(NodeType.TypeIntersectionExpression)
+ {
+ this.Types = types;
+ this.SourceContext = sctx;
+ }
+ }
+ public class TypeUnionExpression : TypeNode, ISymbolicTypeReference
+ {
+ public TypeNodeList Types;
+ public TypeUnionExpression(TypeNodeList types)
+ : base(NodeType.TypeUnionExpression)
+ {
+ this.Types = types;
+ }
+ public TypeUnionExpression(TypeNodeList types, SourceContext sctx)
+ : base(NodeType.TypeUnionExpression)
+ {
+ this.Types = types;
+ this.SourceContext = sctx;
+ }
+ }
+ public class TypeExpression : TypeNode, ISymbolicTypeReference
+ {
+ public Expression Expression;
+ public int Arity;
+
+ public TypeExpression(Expression expression)
+ : base(NodeType.TypeExpression)
+ {
+ this.Expression = expression;
+ }
+ public TypeExpression(Expression expression, TypeNodeList templateArguments)
+ : base(NodeType.TypeExpression)
+ {
+ this.Expression = expression;
+ this.templateArguments = this.TemplateArgumentExpressions = templateArguments;
+ }
+ public TypeExpression(Expression expression, int arity)
+ : base(NodeType.TypeExpression)
+ {
+ this.Expression = expression;
+ this.Arity = arity;
+ }
+ public TypeExpression(Expression expression, SourceContext sctx)
+ : base(NodeType.TypeExpression)
+ {
+ this.Expression = expression;
+ this.SourceContext = sctx;
+ }
+ public TypeExpression(Expression expression, TypeNodeList templateArguments, SourceContext sctx)
+ : base(NodeType.TypeExpression)
+ {
+ this.Expression = expression;
+ this.templateArguments = this.TemplateArgumentExpressions = templateArguments;
+ this.SourceContext = sctx;
+ }
+ public TypeExpression(Expression expression, int arity, SourceContext sctx)
+ : base(NodeType.TypeExpression)
+ {
+ this.Expression = expression;
+ this.Arity = arity;
+ this.SourceContext = sctx;
+ }
+ public override bool IsUnmanaged
+ {
+ get
+ {
+ Literal lit = this.Expression as Literal;
+ if (lit != null)
+ {
+ TypeNode t = lit.Value as TypeNode;
+ if (t != null) return t.IsUnmanaged;
+ if (lit.Value is TypeCode) return true;
+ }
+ return true;
+ }
+ }
+ }
+ public class TypeReference : Node
+ {
+ public TypeNode Type;
+ public TypeNode Expression;
+
+ public TypeReference(TypeNode typeExpression)
+ : base(NodeType.TypeReference)
+ {
+ this.Expression = typeExpression;
+ if (typeExpression != null)
+ this.SourceContext = typeExpression.SourceContext;
+ }
+ public TypeReference(TypeNode typeExpression, TypeNode type)
+ : base(NodeType.TypeReference)
+ {
+ this.Expression = typeExpression;
+ this.Type = type;
+ if (typeExpression != null)
+ this.SourceContext = typeExpression.SourceContext;
+ }
+ public static explicit operator TypeNode(TypeReference typeReference)
+ {
+ return null == (object)typeReference ? null : typeReference.Type;
+ }
+ public static bool operator ==(TypeReference typeReference, TypeNode type)
+ {
+ return null == (object)typeReference ? null == (object)type : typeReference.Type == type;
+ }
+ public static bool operator ==(TypeNode type, TypeReference typeReference)
+ {
+ return null == (object)typeReference ? null == (object)type : typeReference.Type == type;
+ }
+ public static bool operator !=(TypeReference typeReference, TypeNode type)
+ {
+ return null == (object)typeReference ? null != (object)type : typeReference.Type != type;
+ }
+ public static bool operator !=(TypeNode type, TypeReference typeReference)
+ {
+ return null == (object)typeReference ? null != (object)type : typeReference.Type != type;
+ }
+ public override bool Equals(object obj)
+ {
+ return obj == (object)this || obj == (object)this.Type;
+ }
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+ }
+ public class ArglistArgumentExpression : NaryExpression
+ {
+ public ArglistArgumentExpression(ExpressionList args, SourceContext sctx)
+ : base(args, NodeType.ArglistArgumentExpression)
+ {
+ this.SourceContext = sctx;
+ }
+ }
+ public class ArglistExpression : Expression
+ {
+ public ArglistExpression(SourceContext sctx)
+ : base(NodeType.ArglistExpression)
+ {
+ this.SourceContext = sctx;
+ }
+ }
+ public class RefValueExpression : BinaryExpression
+ {
+ public RefValueExpression(Expression typedreference, Expression type, SourceContext sctx)
+ : base(typedreference, type, NodeType.RefValueExpression)
+ {
+ this.SourceContext = sctx;
+ }
+
+ }
+ public class RefTypeExpression : UnaryExpression
+ {
+ public RefTypeExpression(Expression typedreference, SourceContext sctx)
+ : base(typedreference, NodeType.RefTypeExpression)
+ {
+ this.SourceContext = sctx;
+ }
+
+ }
+#endif
+#if ExtendedRuntime
+ public delegate Expression Coercer(Expression source, TypeNode targetType, TypeViewer typeViewer);
+ public sealed class StreamAdapter{
+ private StreamAdapter(){}
+ public static TypeNode For(Interface/*!*/ sourceStream, Interface/*!*/ targetStream, Module/*!*/ module, Coercer/*!*/ coercer, SourceContext sctx) {
+ return StreamAdapter.For(sourceStream, targetStream, null, module, coercer, sctx);
+ }
+ public static TypeNode For(Interface /*!*/sourceStream, Interface/*!*/ targetStream, TypeNode/*!*/ referringType, Coercer/*!*/ coercer, SourceContext sctx) {
+ if (referringType == null){Debug.Assert(false); return null;}
+ return StreamAdapter.For(sourceStream, targetStream, referringType, referringType.DeclaringModule, coercer, sctx);
+ }
+ public static TypeNode For(Interface/*!*/ sourceStream, Interface/*!*/ targetStream, TypeNode referringType, Module/*!*/ module, Coercer/*!*/ coercer, SourceContext sctx) {
+ Debug.Assert(sourceStream.Template == SystemTypes.GenericIEnumerable && targetStream.Template == SystemTypes.GenericIEnumerable);
+ Identifier id = Identifier.For("AdapterFor" + sourceStream.Name + "To" + targetStream.Name);
+ for (int i = 1; ;i++){
+ TypeNode t = module.GetStructurallyEquivalentType(targetStream.Namespace, id);
+ if (t == null) break;
+ if (t.IsAssignableTo(targetStream)){
+ InstanceInitializer cons = t.GetConstructor(sourceStream);
+ if (cons != null) return t;
+ }
+ id = Identifier.For(id.ToString()+i);
+ }
+ Method sGetEnumerator = sourceStream.GetMethod(StandardIds.GetEnumerator);
+ Method tGetEnumerator = targetStream.GetMethod(StandardIds.GetEnumerator);
+ if (sGetEnumerator == null || tGetEnumerator == null) { Debug.Fail(""); return null; }
+ Interface sGetEnumeratorReturnType = (Interface)TypeNode.StripModifiers(sGetEnumerator.ReturnType);
+ Interface tGetEnumeratorReturnType = (Interface)TypeNode.StripModifiers(tGetEnumerator.ReturnType);
+ //^ assert sGetEnumeratorReturnType != null && tGetEnumeratorReturnType != null;
+ TypeNode enumeratorAdapter = null;
+ if (referringType != null)
+ enumeratorAdapter = EnumeratorAdapter.For(id, sGetEnumeratorReturnType, tGetEnumeratorReturnType, referringType, coercer, sctx);
+ else
+ enumeratorAdapter = EnumeratorAdapter.For(id, sGetEnumeratorReturnType, tGetEnumeratorReturnType, module, coercer, sctx);
+ if (enumeratorAdapter == null) return null;
+ InterfaceList interfaces = new InterfaceList(targetStream);
+ MemberList members = new MemberList(3);
+ Class adapter = new Class(module, null, null, TypeFlags.Sealed, targetStream.Namespace, id, CoreSystemTypes.Object, interfaces, members);
+ adapter.IsNormalized = true;
+ if (referringType == null ||
+ (sourceStream.Flags & TypeFlags.VisibilityMask) == TypeFlags.Public && (targetStream.Flags & TypeFlags.VisibilityMask) == TypeFlags.Public){
+ adapter.Flags |= TypeFlags.Public;
+ module.Types.Add(adapter);
+ }else{
+ adapter.Flags |= TypeFlags.NestedPrivate;
+ referringType.Members.Add(adapter);
+ adapter.DeclaringType = referringType;
+ }
+ module.StructurallyEquivalentType[id.UniqueIdKey] = adapter;
+
+ //Field to hold source stream
+ Field ssField = new Field(adapter, null, FieldFlags.Private, StandardIds.Value, sourceStream, null);
+ members.Add(ssField);
+
+ //Constructor
+ This ThisParameter = new This(adapter);
+ Parameter par = new Parameter(null, ParameterFlags.None, StandardIds.Value, sourceStream, null, null);
+ StatementList statements = new StatementList(3);
+ InstanceInitializer cstr = CoreSystemTypes.Object.GetConstructor();
+ if (cstr == null) { Debug.Fail(""); return adapter; }
+ MethodCall mcall = new MethodCall(new MemberBinding(ThisParameter, cstr), new ExpressionList(0), NodeType.Call, CoreSystemTypes.Void);
+ statements.Add(new ExpressionStatement(mcall));
+ statements.Add(new AssignmentStatement(new MemberBinding(ThisParameter, ssField), par));
+ statements.Add(new Return());
+ InstanceInitializer acons = new InstanceInitializer(adapter, null, new ParameterList(par), new Block(statements));
+ acons.Flags |= MethodFlags.Public;
+ acons.ThisParameter = ThisParameter;
+ members.Add(acons);
+
+ //GetEnumerator
+ ThisParameter = new This(adapter);
+ statements = new StatementList(1);
+ mcall = new MethodCall(new MemberBinding(new MemberBinding(ThisParameter, ssField), sGetEnumerator),
+ new ExpressionList(0), NodeType.Callvirt, sGetEnumerator.ReturnType);
+ cstr = enumeratorAdapter.GetConstructor(sGetEnumerator.ReturnType);
+ if (cstr == null) { Debug.Fail(""); return adapter; }
+ Construct constr = new Construct(new MemberBinding(null, cstr), new ExpressionList(mcall));
+ statements.Add(new Return(constr));
+ Method getEnumerator = new Method(adapter, null, StandardIds.GetEnumerator, null, tGetEnumerator.ReturnType, new Block(statements));
+ getEnumerator.Flags = MethodFlags.Public | MethodFlags.Virtual | MethodFlags.NewSlot | MethodFlags.HideBySig;
+ getEnumerator.CallingConvention = CallingConventionFlags.HasThis;
+ getEnumerator.ThisParameter = ThisParameter;
+ members.Add(getEnumerator);
+
+ //IEnumerable.GetEnumerator
+ Method ieGetEnumerator = SystemTypes.IEnumerable.GetMethod(StandardIds.GetEnumerator);
+ if (ieGetEnumerator == null) { Debug.Fail(""); return adapter; }
+ ThisParameter = new This(adapter);
+ statements = new StatementList(1);
+ mcall = new MethodCall(new MemberBinding(new MemberBinding(ThisParameter, ssField), ieGetEnumerator),
+ new ExpressionList(0), NodeType.Callvirt, SystemTypes.IEnumerator);
+ statements.Add(new Return(mcall));
+ getEnumerator = new Method(adapter, null, StandardIds.IEnumerableGetEnumerator, null, SystemTypes.IEnumerator, new Block(statements));
+ getEnumerator.ThisParameter = ThisParameter;
+ getEnumerator.ImplementedInterfaceMethods = new MethodList(ieGetEnumerator);
+ getEnumerator.CallingConvention = CallingConventionFlags.HasThis;
+ getEnumerator.Flags = MethodFlags.Private | MethodFlags.Virtual | MethodFlags.SpecialName;
+ members.Add(getEnumerator);
+
+ return adapter;
+ }
+ }
+ internal sealed class EnumeratorAdapter{
+ private EnumeratorAdapter(){}
+ internal static TypeNode For(Identifier/*!*/ id, Interface/*!*/ sourceIEnumerator, Interface/*!*/ targetIEnumerator, Module/*!*/ module, Coercer/*!*/ coercer, SourceContext sctx) {
+ return EnumeratorAdapter.For(id, sourceIEnumerator, targetIEnumerator, null, module, coercer, sctx);
+ }
+ internal static TypeNode For(Identifier/*!*/ id, Interface/*!*/ sourceIEnumerator, Interface/*!*/ targetIEnumerator, TypeNode/*!*/ referringType, Coercer/*!*/ coercer, SourceContext sctx) {
+ if (referringType == null){Debug.Assert(false); return null;}
+ return EnumeratorAdapter.For(id, sourceIEnumerator, targetIEnumerator, referringType, referringType.DeclaringModule, coercer, sctx);
+ }
+ private static TypeNode For(Identifier/*!*/ id, Interface/*!*/ sourceIEnumerator, Interface/*!*/ targetIEnumerator, TypeNode referringType, Module/*!*/ module, Coercer/*!*/ coercer, SourceContext sctx) {
+ Method sGetCurrent = sourceIEnumerator.GetMethod(StandardIds.getCurrent);
+ if (sGetCurrent == null) { Debug.Fail(""); return null; }
+ Method sMoveNext = sourceIEnumerator.GetMethod(StandardIds.MoveNext);
+ if (sMoveNext == null) sMoveNext = SystemTypes.IEnumerator.GetMethod(StandardIds.MoveNext);
+ Method tGetCurrent = targetIEnumerator.GetMethod(StandardIds.getCurrent);
+ if (tGetCurrent == null) { Debug.Fail(""); return null; }
+ Method tMoveNext = targetIEnumerator.GetMethod(StandardIds.MoveNext);
+ if (tMoveNext == null) tMoveNext = SystemTypes.IEnumerator.GetMethod(StandardIds.MoveNext);
+ Local loc = new Local(sGetCurrent.ReturnType);
+ Expression curr = coercer(loc, tGetCurrent.ReturnType, null);
+ if (curr == null) return null;
+ id = Identifier.For("Enumerator"+id.ToString());
+ InterfaceList interfaces = new InterfaceList(targetIEnumerator, SystemTypes.IDisposable);
+ MemberList members = new MemberList(5);
+ Class adapter = new Class(module, null, null, TypeFlags.Public, targetIEnumerator.Namespace, id, CoreSystemTypes.Object, interfaces, members);
+ adapter.IsNormalized = true;
+ if (referringType == null ||
+ (sourceIEnumerator.Flags & TypeFlags.VisibilityMask) == TypeFlags.Public && (targetIEnumerator.Flags & TypeFlags.VisibilityMask) == TypeFlags.Public){
+ adapter.Flags |= TypeFlags.Public;
+ module.Types.Add(adapter);
+ }else{
+ adapter.Flags |= TypeFlags.NestedPrivate;
+ referringType.Members.Add(adapter);
+ adapter.DeclaringType = referringType;
+ }
+ //Field to hold source enumerator
+ Field seField = new Field(adapter, null, FieldFlags.Private, StandardIds.Value, sourceIEnumerator, null);
+ members.Add(seField);
+
+ //Constructor
+ Parameter par = new Parameter(null, ParameterFlags.None, StandardIds.Value, sourceIEnumerator, null, null);
+ StatementList statements = new StatementList(3);
+ This ThisParameter = new This(adapter);
+ InstanceInitializer constr = CoreSystemTypes.Object.GetConstructor();
+ if (constr == null) { Debug.Fail(""); return null; }
+ MethodCall mcall = new MethodCall(new MemberBinding(ThisParameter, constr),
+ new ExpressionList(0), NodeType.Call, CoreSystemTypes.Void);
+ statements.Add(new ExpressionStatement(mcall));
+ statements.Add(new AssignmentStatement(new MemberBinding(ThisParameter, seField), par));
+ statements.Add(new Return());
+ InstanceInitializer acons = new InstanceInitializer(adapter, null, new ParameterList(par), new Block(statements));
+ acons.Flags |= MethodFlags.Public;
+ acons.ThisParameter = ThisParameter;
+ members.Add(acons);
+
+ //get_Current
+ statements = new StatementList(2);
+ ThisParameter = new This(adapter);
+ mcall = new MethodCall(new MemberBinding(new MemberBinding(ThisParameter, seField), sGetCurrent),
+ new ExpressionList(0), NodeType.Callvirt, sGetCurrent.ReturnType);
+ mcall.SourceContext = sctx;
+ statements.Add(new AssignmentStatement(loc, mcall));
+ statements.Add(new Return(curr));
+ Method getCurrent = new Method(adapter, null, StandardIds.getCurrent, null, tGetCurrent.ReturnType, new Block(statements));
+ getCurrent.Flags = MethodFlags.Public | MethodFlags.Virtual | MethodFlags.NewSlot | MethodFlags.HideBySig | MethodFlags.SpecialName;
+ getCurrent.CallingConvention = CallingConventionFlags.HasThis;
+ getCurrent.ThisParameter = ThisParameter;
+ members.Add(getCurrent);
+
+ //IEnumerator.GetCurrent
+ statements = new StatementList(1);
+ ThisParameter = new This(adapter);
+ MethodCall callGetCurrent = new MethodCall(new MemberBinding(ThisParameter, getCurrent), new ExpressionList(0), NodeType.Call, getCurrent.ReturnType);
+ if (getCurrent.ReturnType.IsValueType) {
+ MemberBinding etExpr = new MemberBinding(null, getCurrent.ReturnType);
+ statements.Add(new Return(new BinaryExpression(callGetCurrent, etExpr, NodeType.Box, CoreSystemTypes.Object)));
+ }else
+ statements.Add(new Return(callGetCurrent));
+ Method ieGetCurrent = new Method(adapter, null, StandardIds.IEnumeratorGetCurrent, null, CoreSystemTypes.Object, new Block(statements));
+ ieGetCurrent.ThisParameter = ThisParameter;
+ ieGetCurrent.ImplementedInterfaceMethods = new MethodList(SystemTypes.IEnumerator.GetMethod(StandardIds.getCurrent));
+ ieGetCurrent.CallingConvention = CallingConventionFlags.HasThis;
+ ieGetCurrent.Flags = MethodFlags.Private | MethodFlags.Virtual | MethodFlags.SpecialName;
+ members.Add(ieGetCurrent);
+
+ //IEnumerator.Reset
+ Method ieReset = SystemTypes.IEnumerator.GetMethod(StandardIds.Reset);
+ if (ieReset == null) { Debug.Fail(""); return null; }
+ statements = new StatementList(2);
+ ThisParameter = new This(adapter);
+ MethodCall callSourceReset = new MethodCall(new MemberBinding(ThisParameter, ieReset), new ExpressionList(0), NodeType.Callvirt, CoreSystemTypes.Object);
+ statements.Add(new ExpressionStatement(callSourceReset));
+ statements.Add(new Return());
+ Method reset = new Method(adapter, null, StandardIds.IEnumeratorReset, null, CoreSystemTypes.Void, new Block(statements));
+ reset.ThisParameter = ThisParameter;
+ reset.ImplementedInterfaceMethods = new MethodList(ieReset);
+ reset.CallingConvention = CallingConventionFlags.HasThis;
+ reset.Flags = MethodFlags.Private | MethodFlags.Virtual | MethodFlags.SpecialName;
+ members.Add(reset);
+
+ //MoveNext
+ if (sMoveNext == null) { Debug.Fail(""); return null; }
+ statements = new StatementList(1);
+ ThisParameter = new This(adapter);
+ mcall = new MethodCall(new MemberBinding(new MemberBinding(ThisParameter, seField), sMoveNext),
+ new ExpressionList(0), NodeType.Callvirt, CoreSystemTypes.Boolean);
+ statements.Add(new Return(mcall));
+ Method moveNext = new Method(adapter, null, StandardIds.MoveNext, null, CoreSystemTypes.Boolean, new Block(statements));
+ moveNext.Flags = MethodFlags.Public | MethodFlags.Virtual | MethodFlags.NewSlot | MethodFlags.HideBySig;
+ moveNext.CallingConvention = CallingConventionFlags.HasThis;
+ moveNext.ThisParameter = ThisParameter;
+ members.Add(moveNext);
+
+ //IDispose.Dispose
+ statements = new StatementList(1);
+ //TODO: call Dispose on source enumerator
+ statements.Add(new Return());
+ Method dispose = new Method(adapter, null, StandardIds.Dispose, null, CoreSystemTypes.Void, new Block(statements));
+ dispose.CallingConvention = CallingConventionFlags.HasThis;
+ dispose.Flags = MethodFlags.Public | MethodFlags.Virtual;
+ adapter.Members.Add(dispose);
+ return adapter;
+ }
+ }
+#endif
+#if FxCop
+ public class EventNode : Member{
+#else
+ public class Event : Member
+ {
+#endif
+ private EventFlags flags;
+ private Method handlerAdder;
+ private Method handlerCaller;
+ private MethodFlags handlerFlags;
+ private Method handlerRemover;
+ private TypeNode handlerType;
+ private MethodList otherMethods;
+#if !MinimalReader
+ public TypeNode HandlerTypeExpression;
+ /// <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>
+ public TypeNodeList ImplementedTypes;
+ public TypeNodeList ImplementedTypeExpressions;
+ /// <summary>Provides a delegate instance that is added to the event upon initialization.</summary>
+ public Expression InitialHandler;
+ public Field BackingField;
+#endif
+#if FxCop
+ public EventNode()
+#else
+ public Event()
+#endif
+ : base(NodeType.Event)
+ {
+ }
+#if !MinimalReader
+ public Event(TypeNode declaringType, AttributeList attributes, EventFlags flags, Identifier name,
+ Method handlerAdder, Method handlerCaller, Method handlerRemover, TypeNode handlerType)
+ : base(declaringType, attributes, name, NodeType.Event)
+ {
+ this.Flags = flags;
+ this.HandlerAdder = handlerAdder;
+ this.HandlerCaller = handlerCaller;
+ this.HandlerRemover = handlerRemover;
+ this.HandlerType = handlerType;
+ }
+#endif
+ /// <summary>Bits characterizing this event.</summary>
+ public EventFlags Flags
+ {
+ get { return this.flags; }
+ set { this.flags = value; }
+ }
+ /// <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>
+ public Method HandlerAdder
+ {
+ get { return this.handlerAdder; }
+ set { this.handlerAdder = value; }
+ }
+ /// <summary>The method that gets called to fire an event. There is no corresponding C# syntax.</summary>
+ public Method HandlerCaller
+ {
+ get { return this.handlerCaller; }
+ set { this.handlerCaller = value; }
+ }
+ public MethodFlags HandlerFlags
+ {
+ get { return this.handlerFlags; }
+ set { this.handlerFlags = value; }
+ }
+ /// <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>
+ public Method HandlerRemover
+ {
+ get { return this.handlerRemover; }
+ set { this.handlerRemover = value; }
+ }
+ /// <summary>The delegate type that a handler for this event must have. Corresponds to the type clause of C# event declaration.</summary>
+ public TypeNode HandlerType
+ {
+ get { return this.handlerType; }
+ set { this.handlerType = value; }
+ }
+ public MethodList OtherMethods
+ {
+ get { return this.otherMethods; }
+ set { this.otherMethods = value; }
+ }
+ protected string fullName;
+ public override string/*!*/ FullName
+ {
+ get
+ {
+ string result = this.fullName;
+ if (result == null)
+ this.fullName = result = this.DeclaringType.FullName + "." + (this.Name == null ? "" : this.Name.ToString());
+ return result;
+ }
+ }
+#if !NoXml
+ protected override Identifier GetDocumentationId()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("E:");
+ if (this.DeclaringType == null) return Identifier.Empty;
+ this.DeclaringType.AppendDocumentIdMangledName(sb, null, null);
+ sb.Append(".");
+ if (this.Name == null) return Identifier.Empty;
+ sb.Append(this.Name.Name);
+ return Identifier.For(sb.ToString());
+ }
+#endif
+#if !NoReflection
+ public static Event GetEvent(System.Reflection.EventInfo eventInfo)
+ {
+ if (eventInfo == null) return null;
+ TypeNode tn = TypeNode.GetTypeNode(eventInfo.DeclaringType);
+ if (tn == null) return null;
+ return tn.GetEvent(Identifier.For(eventInfo.Name));
+ }
+ protected System.Reflection.EventInfo eventInfo;
+ public virtual System.Reflection.EventInfo GetEventInfo()
+ {
+ if (this.eventInfo == null)
+ {
+ TypeNode tn = this.DeclaringType;
+ if (tn == null) return null;
+ Type t = tn.GetRuntimeType();
+ if (t == null) return null;
+ System.Reflection.BindingFlags flags = System.Reflection.BindingFlags.DeclaredOnly;
+ if (this.IsPublic) flags |= System.Reflection.BindingFlags.Public; else flags |= System.Reflection.BindingFlags.NonPublic;
+ if (this.IsStatic) flags |= System.Reflection.BindingFlags.Static; else flags |= System.Reflection.BindingFlags.Instance;
+ this.eventInfo = t.GetEvent(this.Name.ToString(), flags);
+ }
+ return this.eventInfo;
+ }
+#endif
+ /// <summary>
+ /// True if the methods constituting this event are abstract.
+ /// </summary>
+ public bool IsAbstract
+ {
+ get { return (this.HandlerFlags & MethodFlags.Abstract) != 0; }
+ }
+ public override bool IsAssembly
+ {
+ get { return (this.HandlerFlags & MethodFlags.MethodAccessMask) == MethodFlags.Assembly; }
+ }
+ public override bool IsCompilerControlled
+ {
+ get { return (this.HandlerFlags & MethodFlags.MethodAccessMask) == MethodFlags.CompilerControlled; }
+ }
+ public override bool IsFamily
+ {
+ get { return (this.HandlerFlags & MethodFlags.MethodAccessMask) == MethodFlags.Family; }
+ }
+ public override bool IsFamilyAndAssembly
+ {
+ get { return (this.HandlerFlags & MethodFlags.MethodAccessMask) == MethodFlags.FamANDAssem; }
+ }
+ public override bool IsFamilyOrAssembly
+ {
+ get { return (this.HandlerFlags & MethodFlags.MethodAccessMask) == MethodFlags.FamORAssem; }
+ }
+ public bool IsFinal
+ {
+ get { return (this.HandlerFlags & MethodFlags.Final) != 0; }
+ }
+ public override bool IsPrivate
+ {
+ get { return (this.HandlerFlags & MethodFlags.MethodAccessMask) == MethodFlags.Private; }
+ }
+ public override bool IsPublic
+ {
+ get { return (this.HandlerFlags & MethodFlags.MethodAccessMask) == MethodFlags.Public; }
+ }
+ public override bool IsSpecialName
+ {
+ get { return (this.Flags & EventFlags.SpecialName) != 0; }
+ }
+ public override bool IsStatic
+ {
+ get { return (this.HandlerFlags & MethodFlags.Static) != 0; }
+ }
+ /// <summary>
+ /// True if that the methods constituting this event are virtual.
+ /// </summary>
+ public bool IsVirtual
+ {
+ get { return (this.HandlerFlags & MethodFlags.Virtual) != 0; }
+ }
+ public override bool IsVisibleOutsideAssembly
+ {
+ get
+ {
+ return (this.HandlerAdder != null && this.HandlerAdder.IsVisibleOutsideAssembly) ||
+ (this.HandlerCaller != null && this.HandlerCaller.IsVisibleOutsideAssembly) ||
+ (this.HandlerRemover != null && this.HandlerRemover.IsVisibleOutsideAssembly);
+ }
+ }
+ public static readonly Event NotSpecified = new Event();
+ public override Member HiddenMember
+ {
+ get
+ {
+ return this.HiddenEvent;
+ }
+ set
+ {
+ this.HiddenEvent = (Event)value;
+ }
+ }
+ protected Property hiddenEvent;
+ public virtual Event HiddenEvent
+ {
+ get
+ {
+ if (this.hiddenMember == Event.NotSpecified) return null;
+ Event hiddenEvent = this.hiddenMember as Event;
+ if (hiddenEvent != null) return hiddenEvent;
+
+ Method hiddenAdder = this.HandlerAdder == null ? null : this.HandlerAdder.HiddenMethod;
+ Method hiddenCaller = this.HandlerCaller == null ? null : this.HandlerCaller.HiddenMethod;
+ Method hiddenRemover = this.HandlerRemover == null ? null : this.HandlerRemover.HiddenMethod;
+ Event hiddenAdderEvent = hiddenAdder == null ? null : hiddenAdder.DeclaringMember as Event;
+ Event hiddenCallerEvent = hiddenCaller == null ? null : hiddenCaller.DeclaringMember as Event;
+ Event hiddenRemoverEvent = hiddenRemover == null ? null : hiddenRemover.DeclaringMember as Event;
+
+ hiddenEvent = hiddenAdderEvent;
+ if (hiddenCallerEvent != null)
+ {
+ if (hiddenEvent == null ||
+ (hiddenCallerEvent.DeclaringType != null && hiddenCallerEvent.DeclaringType.IsDerivedFrom(hiddenEvent.DeclaringType)))
+ hiddenEvent = hiddenCallerEvent;
+ }
+ if (hiddenRemoverEvent != null)
+ {
+ if (hiddenEvent == null ||
+ (hiddenRemoverEvent.DeclaringType != null && hiddenRemoverEvent.DeclaringType.IsDerivedFrom(hiddenEvent.DeclaringType)))
+ hiddenEvent = hiddenRemoverEvent;
+ }
+ if (hiddenEvent == null)
+ {
+ this.hiddenMember = Event.NotSpecified;
+ return null;
+ }
+ this.hiddenMember = hiddenEvent;
+ return hiddenEvent;
+ }
+ set
+ {
+ this.hiddenMember = value;
+ }
+ }
+ public override Member OverriddenMember
+ {
+ get
+ {
+ return this.OverriddenEvent;
+ }
+ set
+ {
+ this.OverriddenEvent = (Event)value;
+ }
+ }
+ protected Property overriddenEvent;
+ public virtual Event OverriddenEvent
+ {
+ get
+ {
+ if (this.overriddenMember == Event.NotSpecified) return null;
+ Event overriddenEvent = this.overriddenMember as Event;
+ if (overriddenEvent != null) return overriddenEvent;
+
+ Method overriddenAdder = this.HandlerAdder == null ? null : this.HandlerAdder.OverriddenMethod;
+ Method overriddenCaller = this.HandlerCaller == null ? null : this.HandlerCaller.OverriddenMethod;
+ Method overriddenRemover = this.HandlerRemover == null ? null : this.HandlerRemover.OverriddenMethod;
+ Event overriddenAdderEvent = overriddenAdder == null ? null : overriddenAdder.DeclaringMember as Event;
+ Event overriddenCallerEvent = overriddenCaller == null ? null : overriddenCaller.DeclaringMember as Event;
+ Event overriddenRemoverEvent = overriddenRemover == null ? null : overriddenRemover.DeclaringMember as Event;
+
+ overriddenEvent = overriddenAdderEvent;
+ if (overriddenCallerEvent != null)
+ {
+ if (overriddenEvent == null ||
+ (overriddenCallerEvent.DeclaringType != null && overriddenCallerEvent.DeclaringType.IsDerivedFrom(overriddenEvent.DeclaringType)))
+ overriddenEvent = overriddenCallerEvent;
+ }
+ if (overriddenRemoverEvent != null)
+ {
+ if (overriddenEvent == null ||
+ (overriddenRemoverEvent.DeclaringType != null && overriddenRemoverEvent.DeclaringType.IsDerivedFrom(overriddenEvent.DeclaringType)))
+ overriddenEvent = overriddenRemoverEvent;
+ }
+ if (overriddenEvent == null)
+ {
+ this.overriddenMember = Event.NotSpecified;
+ return null;
+ }
+ this.overriddenMember = overriddenEvent;
+ return overriddenEvent;
+ }
+ set
+ {
+ this.overriddenMember = value;
+ }
+ }
+#if FxCop
+ internal override void GetName(MemberFormat options, StringBuilder name)
+ {
+ base.GetName(options, name);
+ Method.AppendReturnType(options.ReturnType, this.HandlerType, name);
+ }
+#endif
+ }
+
+#if ExtendedRuntime
+ public abstract class MethodContractElement : Node{
+ protected MethodContractElement(NodeType nodeType)
+ : base(nodeType){
+ }
+ public bool Inherited;
+ }
+ public abstract class Requires : MethodContractElement {
+ public Expression Condition;
+ protected Requires()
+ : base(NodeType.Requires) {}
+ protected Requires(NodeType nodeType)
+ : base(nodeType){
+ }
+ protected Requires(NodeType nodeType, Expression expression)
+ : base(nodeType){
+ Condition = expression;
+ }
+ }
+ public class RequiresPlain : Requires {
+ public RequiresPlain()
+ : base(NodeType.RequiresPlain) {}
+ public RequiresPlain(Expression expression)
+ : base(NodeType.RequiresPlain, expression) {}
+ }
+ public class OldExpression : Expression {
+ public Expression expression;
+ public OldExpression()
+ : base(NodeType.OldExpression) {}
+ public OldExpression(Expression expression)
+ : base(NodeType.OldExpression) {this.expression = expression;}
+ }
+ public class RequiresOtherwise : Requires {
+ /// <summary>
+ /// The ThrowException can be a type reference (like "NullReferenceException")
+ /// or a value that would evaluate to something of an exception type.
+ /// (like new NullReferenceException("...") or C.f where the f is a static field
+ /// of class C whose type is an exception.
+ /// </summary>
+ public Expression ThrowException;
+ public RequiresOtherwise()
+ : base(NodeType.RequiresOtherwise) {}
+ public RequiresOtherwise(Expression cond, Expression exc)
+ : base(NodeType.RequiresOtherwise, cond){ ThrowException = exc; }
+ }
+
+ abstract public class Ensures : MethodContractElement {
+ public Expression PostCondition;
+ protected Ensures()
+ : base(NodeType.Ensures) {}
+ protected Ensures(NodeType nodeType)
+ : base(nodeType){
+ }
+ protected Ensures(NodeType nodeType, Expression expression)
+ : base(nodeType){
+ this.PostCondition = expression;
+ }
+ }
+ public class EnsuresNormal : Ensures{
+ public EnsuresNormal()
+ : base(NodeType.EnsuresNormal){
+ }
+ public EnsuresNormal(Expression expression)
+ : base(NodeType.EnsuresNormal, expression){
+ }
+ }
+ public class EnsuresExceptional : Ensures{
+ public TypeNode Type;
+ public TypeNode TypeExpression;
+ public Expression Variable;
+ public EnsuresExceptional()
+ : base(NodeType.EnsuresExceptional){
+ }
+ public EnsuresExceptional(Expression expression)
+ : base(NodeType.EnsuresExceptional, expression){
+ }
+ }
+
+ public class ContractDeserializerContainer{
+ public static IContractDeserializer ContractDeserializer;
+ }
+ public class MethodContract : Node{
+ public Method/*!*/ DeclaringMethod;
+ public Method/*!*/ OriginalDeclaringMethod;
+ protected internal RequiresList requires;
+ protected internal EnsuresList ensures;
+ protected internal ExpressionList modifies;
+ private static SourceContext SetContext(string/*!*/ filename, int startLine, int startCol, int endLine, int endCol, string/*!*/ sourceText) {
+ SourceContext context;
+ context.Document = new DocumentWithPrecomputedLineNumbers(filename, startLine, startCol, endLine, endCol);
+ context.StartPos = 0;
+ context.EndPos = sourceText.Length;
+ context.Document.Text = new DocumentText(sourceText);
+ context.Document.Text.Length = sourceText.Length;
+ return context;
+ }
+ public static SourceContext GetSourceContext(AttributeNode/*!*/ attr) {
+ string filename = "";
+ int startLine = 0;
+ int startCol = 0;
+ int endLine = 0;
+ int endCol = 0;
+ string sourceText = "";
+ if (attr.Expressions != null) {
+ for (int expIndex = 1, expLen = attr.Expressions.Count; expIndex < expLen; expIndex++) {
+ NamedArgument na = attr.Expressions[expIndex] as NamedArgument;
+ if (na == null || na.Name == null) continue;
+ Literal lit = na.Value as Literal;
+ if (lit == null) continue;
+ switch (na.Name.Name) {
+ case "Filename":
+ case "FileName":
+ filename = (string)lit.Value; break;
+ case "StartColumn": startCol = (int)lit.Value; break;
+ case "StartLine": startLine = (int)lit.Value; break;
+ case "EndColumn": endCol = (int)lit.Value; break;
+ case "EndLine": endLine = (int)lit.Value; break;
+ case "SourceText": sourceText = (string)lit.Value; break;
+ default: break;
+ }
+ }
+ }
+ SourceContext ctx = SetContext(filename, startLine, startCol, endLine, endCol,sourceText);
+ return ctx;
+ }
+ public RequiresList Requires{
+ get{
+ if (this.requires != null) return this.requires;
+ RequiresList rs = this.requires = new RequiresList();
+ if (this.DeclaringMethod != null){
+ if (this.Specializer != null && this.DeclaringMethod.Template != null) {
+ this.CopyFrom(this.DeclaringMethod.Template.Contract);
+ this.ensures = (EnsuresList)this.Specializer(this.DeclaringMethod, this.ensures);
+ return this.requires = (RequiresList)this.Specializer(this.DeclaringMethod, this.requires);
+ }
+ AttributeList attributes = this.DeclaringMethod.Attributes;
+ if (attributes == null || attributes.Count == 0) return rs;
+ IContractDeserializer ds = Cci.ContractDeserializerContainer.ContractDeserializer;
+ if (ds != null){
+ TypeNode t = this.DeclaringMethod.DeclaringType;
+ ds.CurrentAssembly = t == null ? null : t.DeclaringModule;
+ for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++){
+ AttributeNode attr = attributes[i];
+ if (attr == null) continue;
+ MemberBinding mb = attr.Constructor as MemberBinding;
+ if (mb != null){
+ if (mb.BoundMember == null) continue;
+ if (mb.BoundMember.DeclaringType != SystemTypes.RequiresAttribute) continue;
+ if (attr.Expressions == null || !(attr.Expressions.Count > 0)) continue;
+
+ Literal l = attr.Expressions[0] as Literal;
+ if (l == null) continue;
+ string s = (string) l.Value;
+ Expression e = null;
+ try {
+ e = ds.ParseContract(this,s,null);
+ } catch {
+ continue; //return this.requires = new RequiresList();
+ }
+ if (e != null){
+ RequiresPlain rp = new RequiresPlain(e);
+ SourceContext ctx = MethodContract.GetSourceContext(attr);
+ e.SourceContext = ctx;
+ rs.Add(rp);
+ }
+ }
+ }
+ ds.CurrentAssembly = null;
+ }
+ }
+ return this.requires;
+ }
+ set{
+ this.requires = value;
+ }
+ }
+ public EnsuresList Ensures{
+ get{
+ if (this.ensures != null) return this.ensures;
+ EnsuresList es = this.ensures = new EnsuresList();
+ if (this.DeclaringMethod != null){
+ if (this.Specializer != null && this.DeclaringMethod.Template != null) {
+ this.CopyFrom(this.DeclaringMethod.Contract);
+ this.requires = (RequiresList)this.Specializer(this.DeclaringMethod, this.requires);
+ return this.ensures = (EnsuresList)this.Specializer(this.DeclaringMethod, this.ensures);
+ }
+ AttributeList attributes = this.DeclaringMethod.Attributes;
+ if (attributes == null || attributes.Count == 0) return es;
+ IContractDeserializer ds = Cci.ContractDeserializerContainer.ContractDeserializer;
+ if (ds != null){
+ TypeNode t = this.DeclaringMethod.DeclaringType;
+ ds.CurrentAssembly = t == null ? null : t.DeclaringModule;
+ for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++){
+ AttributeNode attr = attributes[i];
+ if (attr == null) continue;
+ MemberBinding mb = attr.Constructor as MemberBinding;
+ if (mb != null){
+ if (mb.BoundMember == null) continue;
+ if (mb.BoundMember.DeclaringType != SystemTypes.EnsuresAttribute) continue;
+ if (attr.Expressions == null || !(attr.Expressions.Count > 0)) continue;
+ Literal l = attr.Expressions[0] as Literal;
+ if (l == null) continue;
+ string s = (string) l.Value;
+ Expression e = null;
+ try {
+ e = ds.ParseContract(this,s,null);
+ } catch {
+ continue; //return this.ensures = new EnsuresList();
+ }
+ EnsuresNormal ens = new EnsuresNormal(e);
+ SourceContext ctx = MethodContract.GetSourceContext(attr);
+ e.SourceContext = ctx;
+ es.Add(ens);
+ }
+ }
+ ds.CurrentAssembly = null;
+ }
+ }
+ return this.ensures;
+ }
+ set{
+ this.ensures = value;
+ }
+ }
+ public ExpressionList Modifies{
+ get{
+ if (this.modifies != null) return this.modifies;
+ ExpressionList ms = this.modifies = new ExpressionList();
+ if (this.DeclaringMethod != null){
+ AttributeList attributes = this.DeclaringMethod.Attributes;
+ if (attributes == null || attributes.Count == 0) return ms;
+ IContractDeserializer ds = Cci.ContractDeserializerContainer.ContractDeserializer;
+ if (ds != null){
+ TypeNode t = this.DeclaringMethod.DeclaringType;
+ ds.CurrentAssembly = t == null ? null : t.DeclaringModule;
+ for (int i = 0, n = attributes == null || attributes.Count == 0 ? 0 : attributes.Count; i < n; i++) {
+ AttributeNode attr = attributes[i];
+ if (attr == null) continue;
+ MemberBinding mb = attr.Constructor as MemberBinding;
+ if (mb != null){
+ if (mb.BoundMember == null) continue;
+ if (mb.BoundMember.DeclaringType != SystemTypes.ModifiesAttribute) continue;
+ if (attr.Expressions == null || !(attr.Expressions.Count > 0)) continue;
+
+ Literal l = attr.Expressions[0] as Literal;
+ if (l == null) continue;
+ string s = (string) l.Value;
+ Expression e = ds.ParseContract(this,s,null);
+ if (e == null) continue;
+ SourceContext ctx = MethodContract.GetSourceContext(attr);
+ e.SourceContext = ctx;
+ ms.Add(e);
+ }
+ }
+ ds.CurrentAssembly = null;
+ }
+ }
+ return this.modifies;
+ }
+ set{
+ this.modifies = value;
+ }
+ }
+ public Local LocalForResult;
+ public delegate object ContractSpecializerDelegate(Method method, object part);
+ public ContractSpecializerDelegate Specializer;
+ public MethodContract(Method/*!*/ declaringMethod)
+ : base(NodeType.MethodContract) {
+ this.DeclaringMethod = this.OriginalDeclaringMethod = declaringMethod;
+ }
+
+
+ public void CopyFrom(MethodContract sourceContract) {
+ if ( sourceContract == null ) return;
+ this.OriginalDeclaringMethod = sourceContract.OriginalDeclaringMethod;
+
+ // Force deserialization (if necessary) to make sure sourceContract is fully populated
+ // This is needed for LocalForResult: it is populated in the sourceContract only if the
+ // postconditions have been deserialized.
+ int dummy = sourceContract.Requires.Count;
+ dummy = sourceContract.Ensures.Count + dummy;
+
+ TypeNode t = this.DeclaringMethod.DeclaringType;
+ Module m = t.DeclaringModule;
+ Duplicator dup = new Duplicator(m,t);
+ // Set up DuplicateFor table: all references to parameters from the source contract should be replaced
+ // with references to the equivalent parameter from the target contract.
+ // These references can be of type "Parameter" or "ParameterField".
+ // Also, the local that holds the "result" of the method should be likewise mapped.
+ // Also, the "this" parameter should be mapped.
+ Method sourceMethod = sourceContract.DeclaringMethod;
+ if (sourceMethod != null){
+ MethodScope sourceScope = sourceMethod.Scope;
+ Method targetMethod = this.DeclaringMethod;
+ if (targetMethod != null){
+ #region Map the self parameter
+ if (sourceMethod.ThisParameter != null && targetMethod.ThisParameter != null){
+ dup.DuplicateFor[sourceMethod.ThisParameter.UniqueKey] = targetMethod.ThisParameter;
+ }
+ #endregion
+ #region Map the method parameters
+ if (sourceMethod.Parameters != null && targetMethod.Parameters != null
+ && sourceMethod.Parameters.Count == targetMethod.Parameters.Count){
+ for (int i = 0, n = sourceMethod.Parameters.Count; i < n; i++){
+ dup.DuplicateFor[sourceMethod.Parameters[i].UniqueKey] = targetMethod.Parameters[i];
+ }
+ }
+ #endregion
+ #region Map the ParameterFields
+ MethodScope targetScope = targetMethod.Scope;
+ if (sourceScope != null && targetScope != null){
+ MemberList sourceScopeMembers = sourceScope.Members;
+ for (int i = 0, n = sourceScopeMembers != null ? sourceScopeMembers.Count : 0; i < n; i++){
+ ParameterField sourcePF = sourceScopeMembers[i] as ParameterField;
+ if (sourcePF == null) continue;
+ Parameter sourceP = sourcePF.Parameter;
+ if (sourceP == null){ Debug.Assert(false); continue; }
+ int index = sourceP.ParameterListIndex;
+ if (targetMethod.Parameters == null || targetMethod.Parameters.Count <= index || index < 0){
+ Debug.Assert(false); continue;
+ }
+ Parameter targetParameter = targetMethod.Parameters[index];
+ Field f = targetScope.GetField(targetParameter.Name);
+ if (f == null){ Debug.Assert(false); continue; }
+ ParameterField targetPF = f as ParameterField;
+ if (targetPF == null){ Debug.Assert(false); continue; }
+ dup.DuplicateFor[sourcePF.UniqueKey] = targetPF;
+ }
+ }
+ #endregion
+ }
+ }
+ if ( sourceContract.LocalForResult != null ) {
+ if (this.LocalForResult == null)
+ this.LocalForResult = sourceContract.LocalForResult;
+ dup.DuplicateFor[sourceContract.LocalForResult.UniqueKey] = this.LocalForResult;
+ }
+ MethodContract duplicatedMC = dup.VisitMethodContract(sourceContract);
+ if (duplicatedMC != null && duplicatedMC.Requires != null && duplicatedMC.Requires.Count > 0) {
+ RequiresList reqList = new RequiresList();
+ for (int i = 0, n = duplicatedMC.Requires.Count; i< n; i++){
+ Requires r = duplicatedMC.Requires[i];
+ if (r != null) r.Inherited = true;
+ reqList.Add(r);
+ }
+ foreach(Requires r in this.Requires) {
+ reqList.Add(r);
+ }
+ this.Requires = reqList;
+ }
+ if (duplicatedMC != null && duplicatedMC.Ensures != null && duplicatedMC.Ensures.Count > 0 ) {
+ // Copy only those "throws" ensures for which the target contract does not have
+ // an extension. The checking that is done before calling this method is assumed
+ // to have signalled an error if needed, so there is no checking done here.
+ // REVIEW: should this just be done during the checking and then don't copy any of
+ // the ensures in this method?
+ EnsuresList enList = new EnsuresList();
+ for(int i = 0, n = duplicatedMC.Ensures.Count; i < n; i++) {
+ Ensures e = duplicatedMC.Ensures[i];
+ e.Inherited = true;
+ EnsuresExceptional superThrows = e as EnsuresExceptional;
+ if (superThrows == null){
+ // normal ensures
+ enList.Add(e);
+ continue;
+ }
+ bool found = false;
+ for (int j = 0, subEnsuresLength = this.Ensures == null ? 0 : this.Ensures.Count; j < subEnsuresLength && !found; j++){
+ EnsuresExceptional subThrows = this.Ensures[j] as EnsuresExceptional;
+ if (subThrows == null || subThrows.Type == null) continue;
+ if (subThrows.Type.IsAssignableTo(superThrows.Type))
+ found = true;
+ }
+ if(!found)
+ enList.Add(e);
+ }
+ foreach(Ensures e in this.Ensures) {
+ enList.Add(e);
+ }
+ this.Ensures = enList;
+ }
+ if (duplicatedMC != null && duplicatedMC.Modifies != null && duplicatedMC.Modifies.Count > 0) {
+ ExpressionList modlist = this.Modifies = (this.Modifies == null ? new ExpressionList() : this.Modifies);
+ for (int i = 0, n = duplicatedMC.Modifies.Count; i < n; i++)
+ modlist.Add(duplicatedMC.Modifies[i]);
+ }
+ return;
+ }
+ }
+
+ public class Invariant : Method{
+ public Expression Condition;
+ public Invariant(TypeNode declaringType, AttributeList attributes, Identifier name){
+ this.NodeType = NodeType.Invariant;
+ this.attributes = attributes;
+ this.DeclaringType = declaringType;
+ this.Name = name;
+ // this is called from the parser, so we have to avoid triggering CoreSystemType initialization.
+ this.ReturnType = new TypeExpression(new Literal(TypeCode.Boolean), 0);
+ this.ReturnTypeExpression = new TypeExpression(new Literal(TypeCode.Boolean), 0);
+ }
+ }
+
+ public class ModelfieldContract : Node {
+ protected Field mf; //the modelfield this contract applies to (might be a temporary modelfield that stores unresolved override information)
+ protected Property ifaceMf; //the interface modelfield this contract applies to.
+ //invariant mf != null && ifaceMF == null || mf == null && ifaceMf != null;
+
+ public Expression Witness;
+ public ExpressionList/*!*/ SatisfiesList = new ExpressionList();
+
+ public TypeNode DeclaringType;
+
+ public Member/*!*/ Modelfield { get { return this.mf == null ? (Member)this.ifaceMf : (Member)this.mf; } }
+ public TypeNode/*!*/ ModelfieldType { get { return this.mf == null ? this.ifaceMf.Type : this.mf.Type; } }
+ private bool isOverride = false;
+ public bool IsOverride {
+ //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.
+ get {
+ if (this.isOverride == true) return true;
+ return !(this.Modelfield.DeclaringType == this.DeclaringType);
+ }
+ set {
+ //requires value == true; (setting to false has no real meaning or effect)
+ isOverride = value;
+ }
+ }
+
+ private bool isSealed = false; //set to true if modelfield itself is sealed (i.e., has the keyword).
+ public bool IsSealed {
+ get { if (this.isSealed) return true;
+ if (this.DeclaringType == null) return false; //defensive check
+ return this.DeclaringType.IsSealed;
+ }
+ set { //requires value == true and the modelfield(contract) itself is sealed</summary>
+ this.isSealed = value; }
+ }
+
+ /// <summary>
+ /// ensures that the result is a new modelfieldcontract with an empty set of satisfies clauses and a default witness.
+ /// ensures that the SourceContext of the result and the default witness are set to sctx.
+ /// requires all attributes to be non-null
+ /// </summary>
+ public ModelfieldContract(TypeNode declaringType, AttributeList attrs, TypeNode type, Identifier name, SourceContext sctx)
+ : base(NodeType.ModelfieldContract)
+ {
+ this.DeclaringType = declaringType;
+ this.SourceContext = sctx;
+ if (declaringType is Class) {
+ 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.
+ mf.IsModelfield = true;
+ mf.SourceContext = this.SourceContext;
+ } else if (declaringType is Interface) {
+ //Treat as a property with a getter that will return a modelfield from an implementing class
+ #region create a default abstract getter method getM
+ Method getM = new Method(declaringType, new AttributeList(), new Identifier("get_" + name.Name), new ParameterList(), type, null);
+ getM.SourceContext = this.SourceContext;
+ getM.CallingConvention = CallingConventionFlags.HasThis; //needs to be changed when we want to allow static modelfields
+ declaringType.Members.Add(getM);
+ getM.Flags = MethodFlags.Public | MethodFlags.Abstract | MethodFlags.NewSlot | MethodFlags.Virtual | MethodFlags.SpecialName | MethodFlags.HideBySig;
+ #endregion
+ ifaceMf = new Property(declaringType, attrs, PropertyFlags.None, name, getM, null);
+ ifaceMf.IsModelfield = true;
+ ifaceMf.SourceContext = this.SourceContext;
+ getM.DeclaringMember = ifaceMf;
+ }
+ this.setWitnessToDefault();
+ }
+
+ /// <summary>
+ /// ensures result.HasDefaultWitness and result.Modelfield == modelfield
+ /// </summary>
+ public ModelfieldContract(TypeNode/* ! */ declaringType, Field/* ! */ modelfield)
+ : base(NodeType.ModelfieldContract) {
+ this.DeclaringType = declaringType;
+ this.SourceContext = modelfield.SourceContext;
+ this.mf = modelfield;
+ this.setWitnessToDefault();
+ if (modelfield.DeclaringType != declaringType)
+ this.IsOverride = true;
+ }
+
+ private void setWitnessToDefault() {
+ if (this.ModelfieldType.IsReferenceType)
+ this.Witness = new Literal(null, this.ModelfieldType, this.SourceContext); //this.HasDefaultWitness relies on this intialization of witness.sourcecontext.
+ else
+ this.Witness = new Literal(0, this.ModelfieldType, this.SourceContext); //this.HasDefaultWitness relies on this intialization of witness.sourcecontext.
+ }
+
+ /// <summary>
+ /// requires this.IsOverride == true;
+ /// requires that newMf is a member of a superclass of mfC.DeclaringType;
+ /// ensures this.Modelfield == newMf;
+ /// use this method to update the modelfield of an overriding modelfieldcontract to the modelfield that is overridden.
+ /// </summary>
+ /// <param name="newMf">The overridden modelfield that this modelfieldContract applies to</param>
+ public void UpdateModelfield(Field newMf) {
+ this.mf = newMf;
+ }
+
+ public bool HasDefaultWitness { get { return this.Witness.SourceContext.Equals(this.SourceContext); } }
+
+
+ private ModelfieldContract nearestOverriddenContract; //null when this not an overriding contract (or when getNearestContractContract has not yet been called)
+ /// <summary>
+ /// ensures: if this contract overrides a superclass contract, then result is the nearest overridden contract, else result == null.
+ /// </summary>
+ public ModelfieldContract NearestOverriddenContract {
+ get {
+ if (this.nearestOverriddenContract != null) return this.nearestOverriddenContract;
+
+ if (this.mf == null) return null; //interface modelfieldContracts can't override
+ if (!this.IsOverride) return null;
+ #region scan superclasses until nearest overriden contract is found, then return that contract.
+ for (Class currentClass = this.DeclaringType.BaseType as Class; currentClass != null; currentClass = currentClass.BaseClass) {
+ foreach (ModelfieldContract currentMfC in currentClass.Contract.ModelfieldContracts) {
+ if (currentMfC.Modelfield == this.mf) {
+ this.nearestOverriddenContract = currentMfC;
+ return this.nearestOverriddenContract;
+ }
+ }
+ }
+ Debug.Assert(false); //an overridden contract should have been found and returned.
+ return this.nearestOverriddenContract;
+ #endregion
+ }
+ }
+
+ }
+
+ public sealed class ModelfieldContractList {
+ private ModelfieldContract[]/*!*/ elements;
+ private int count = 0;
+ public ModelfieldContractList() {
+ this.elements = new ModelfieldContract[8];
+ //^ base();
+ }
+ public ModelfieldContractList(int n) {
+ this.elements = new ModelfieldContract[n];
+ //^ base();
+ }
+ public ModelfieldContractList(params ModelfieldContract[] elements) {
+ if (elements == null) elements = new ModelfieldContract[0];
+ this.elements = elements;
+ this.count = elements.Length;
+ //^ base();
+ }
+ public void Add(ModelfieldContract element) {
+ int n = this.elements.Length;
+ int i = this.count++;
+ if (i == n) {
+ int m = n * 2; if (m < 8) m = 8;
+ ModelfieldContract[] newElements = new ModelfieldContract[m];
+ for (int j = 0; j < n; j++) newElements[j] = elements[j];
+ this.elements = newElements;
+ }
+ this.elements[i] = element;
+ }
+ public ModelfieldContractList/*!*/ Clone() {
+ ModelfieldContract[] elements = this.elements;
+ int n = this.count;
+ ModelfieldContractList result = new ModelfieldContractList(n);
+ result.count = n;
+ ModelfieldContract[] newElements = result.elements;
+ for (int i = 0; i < n; i++)
+ newElements[i] = elements[i];
+ return result;
+ }
+ public int Count {
+ get { return this.count; }
+ set { this.count = value; }
+ }
+ [Obsolete("Use Count property instead.")]
+ public int Length {
+ get { return this.count; }
+ set { this.count = value; }
+ }
+ public ModelfieldContract this[int index] {
+ get {
+ return this.elements[index];
+ }
+ set {
+ this.elements[index] = value;
+ }
+ }
+ public Enumerator GetEnumerator() {
+ return new Enumerator(this);
+ }
+ public struct Enumerator {
+ private int index;
+ private readonly ModelfieldContractList/*!*/ list;
+ public Enumerator(ModelfieldContractList/*!*/ list) {
+ this.index = -1;
+ this.list = list;
+ }
+ public ModelfieldContract Current {
+ get {
+ return this.list[this.index];
+ }
+ }
+ public bool MoveNext() {
+ return ++this.index < this.list.count;
+ }
+ public void Reset() {
+ this.index = -1;
+ }
+ }
+ }
+
+ public class TypeContract : Node {
+ public TypeNode DeclaringType;
+ protected internal ModelfieldContractList modelfieldContracts;
+
+ /// <summary>
+ /// Deserializes attr.Expressions[i] as expression E.
+ /// requires attr.Expressions.Count > i;
+ /// requires this.DeclaringType != null;
+ /// </summary>
+ /// <returns>E if succesfull, null otherwise.</returns>
+ private Expression getIndexFromAttribute(AttributeNode attr, int i) {
+ IContractDeserializer ds = Cci.ContractDeserializerContainer.ContractDeserializer;
+ if (ds == null) return null;
+ ds.CurrentAssembly = this.DeclaringType.DeclaringModule;
+ Literal l = attr.Expressions[i] as Literal;
+ if (l == null) return null;
+ string s = (string)l.Value;
+ return ds.ParseContract(this, s, null);
+ }
+
+ /// <summary>
+ /// requires attr.Expressions.Count > 0
+ /// ensures if attr.Expressions[0] can be deserialized as modelfield F, then:
+ /// if F key in contractLookup, then returns matching value, else returns new ModelfieldContract mfC for F
+ /// else returns null
+ /// ensures if new mfC created, then (F, mfC) in contractLookup and mfC in this.ModelfieldContracts
+ /// </summary>
+ private ModelfieldContract getContractFor(AttributeNode attr, Dictionary<Field, ModelfieldContract> contractLookup) {
+ Expression mfBinding = this.getIndexFromAttribute(attr, 0);
+
+ //extract modelfield from mfBinding
+ if (!(mfBinding is MemberBinding)) return null;
+ Field modelfield = (mfBinding as MemberBinding).BoundMember as Field;
+ if (modelfield == null) return null;
+
+ //If this modelfield does not yet have a contract, then create one now and add <modelfield,mfC> to createdContracts
+ ModelfieldContract mfC = null;
+ if (!contractLookup.TryGetValue(modelfield, out mfC)) {
+ mfC = new ModelfieldContract(this.DeclaringType, modelfield);
+ this.modelfieldContracts.Add(mfC);
+ contractLookup.Add(modelfield, mfC);
+ }
+
+ return mfC;
+ }
+
+ public ModelfieldContractList/*!*/ ModelfieldContracts {
+ get {
+ if (this.modelfieldContracts == null) {
+ this.modelfieldContracts = new ModelfieldContractList();
+ #region deserialize the modelfieldcontracts if needed
+ Dictionary<Field,ModelfieldContract> createdContracts = new Dictionary<Field,ModelfieldContract>(); //key = modelfield memberbinding, value = contract for that modelfield (if one was created already)
+ if (this.DeclaringType != null) {
+ foreach (AttributeNode attr in this.DeclaringType.Attributes) {
+ if (attr == null) continue;
+ MemberBinding mb = attr.Constructor as MemberBinding;
+ if (mb == null || mb.BoundMember == null) continue;
+ if (mb.BoundMember.DeclaringType == SystemTypes.ModelfieldContractAttribute) {
+ ModelfieldContract mfC = this.getContractFor(attr, createdContracts);
+ Expression witness = this.getIndexFromAttribute(attr, 1);
+ if (witness == null) continue;
+ witness.SourceContext = MethodContract.GetSourceContext(attr);
+ mfC.Witness = witness;
+ } else if (mb.BoundMember.DeclaringType == SystemTypes.SatisfiesAttribute) {
+ ModelfieldContract mfC = this.getContractFor(attr, createdContracts);
+ Expression satClause = this.getIndexFromAttribute(attr, 1);
+ if (satClause == null) continue;
+ satClause.SourceContext = MethodContract.GetSourceContext(attr);
+ mfC.SatisfiesList.Add(satClause);
+ }
+ }
+ }
+ #endregion
+ }
+ return this.modelfieldContracts;
+ }
+ set { this.modelfieldContracts = value; }
+ }
+
+ public InvariantList InheritedInvariants;
+ protected internal InvariantList invariants;
+ public InvariantList Invariants{
+ get{
+ if (this.invariants != null) return this.invariants;
+ InvariantList invs = this.invariants = new InvariantList();
+ if (this.DeclaringType != null){
+ AttributeList attributes = this.DeclaringType.Attributes;
+ IContractDeserializer ds = Cci.ContractDeserializerContainer.ContractDeserializer;
+ if (ds != null){
+ ds.CurrentAssembly = this.DeclaringType == null ? null : this.DeclaringType.DeclaringModule;
+ for (int i = 0, n = attributes == null || attributes.Count == 0 ? 0 : attributes.Count; i < n; i++){
+ AttributeNode attr = attributes[i];
+ if (attr == null) continue;
+ MemberBinding mb = attr.Constructor as MemberBinding;
+ if (mb != null){
+ if (mb.BoundMember == null) continue;
+ if (mb.BoundMember.DeclaringType != SystemTypes.InvariantAttribute) continue;
+ if (attr.Expressions == null || !(attr.Expressions.Count > 0)) continue;
+
+ Literal l = attr.Expressions[0] as Literal;
+ if (l == null) continue;
+ string s = (string) l.Value;
+ Expression e = ds.ParseContract(this,s,null);
+ if (e != null){
+ Invariant inv = new Invariant(this.DeclaringType,null,Identifier.For("invariant"+i));
+ SourceContext ctx = MethodContract.GetSourceContext(attr);
+ inv.SourceContext = ctx;
+ inv.Condition = e;
+ invs.Add(inv);
+ }
+ }
+ }
+ // Make the type contract look as it does when the type is compiled from source
+ this.FramePropertyGetter = this.DeclaringType.GetMethod(Identifier.For("get_SpecSharp::FrameGuard"), null);
+ this.InitFrameSetsMethod = this.DeclaringType.GetMethod(Identifier.For("SpecSharp::InitGuardSets"), null);
+ this.InvariantMethod = this.DeclaringType.GetMethod(Identifier.For("SpecSharp::CheckInvariant"), CoreSystemTypes.Boolean);
+ this.FrameProperty = this.DeclaringType.GetProperty(Identifier.For("SpecSharp::FrameGuard"));
+ this.FrameField = this.DeclaringType.GetField(Identifier.For("SpecSharp::frameGuard"));
+ ds.CurrentAssembly = null;
+ }
+ }
+ return this.invariants;
+ }
+ set{
+ this.invariants = value;
+ }
+ }
+
+ // when non-null, points to the method added to the DeclaringType that will have the invariants in its body
+ // needed so when each invariant is visited, the proper environment can be set up for it.
+ // NB: Dont' visit it as part of StandardVisitor
+ public Field FrameField;
+ public Property FrameProperty;
+ public Method FramePropertyGetter;
+ public Method InitFrameSetsMethod;
+ public Method InvariantMethod;// when non-null, points to the method added to the DeclaringType that will have the invariants in its body
+ /// <summary>
+ /// Microsoft.Contracts.FrameGuardGetter implementation for this class.
+ /// </summary>
+ public Method GetFrameGuardMethod;
+ /// <summary>
+ /// When types get constructed via the Reader, we let the Invariants be initialized on demand.
+ /// When the parser creates a type, we want the type contract to contain the empty invariant list
+ /// so that it won't grovel through the attributes on first access to Invariants.
+ /// </summary>
+ /// <param name="containingType"></param>
+ public TypeContract(TypeNode containingType) : this(containingType, false)
+ {
+ }
+ public TypeContract(TypeNode containingType, bool initInvariantList)
+ : base(NodeType.TypeContract) {
+ this.DeclaringType = containingType;
+ if (initInvariantList) {
+ this.invariants = new InvariantList();
+ }
+ }
+ public int InvariantCount { get { return Invariants == null ? 0 : Invariants.Count; } }
+ public int ModelfieldContractCount { get { return ModelfieldContracts == null ? 0 : ModelfieldContracts.Count; } }
+ }
+ public interface IContractDeserializer{
+ // when text is a requires, ensures, or modifies
+ Expression ParseContract(MethodContract mc, string text, ErrorNodeList errors);
+ // when text is an assertion or an assume in code
+ Expression ParseContract(Method m, string text, ErrorNodeList errs);
+ // when text is an invariant
+ Expression ParseContract(TypeContract/*!*/ tc, string text, ErrorNodeList errs);
+ Module CurrentAssembly { get; set; }
+ ErrorNodeList ErrorList { get; set; }
+ }
+#endif
+
+ public class Method : Member
+ {
+#if ExtendedRuntime
+ public MethodContract Contract;
+#endif
+#if !MinimalReader
+ public TypeNodeList ImplementedTypes;
+ public TypeNodeList ImplementedTypeExpressions;
+ public bool HasCompilerGeneratedSignature = true;
+ public TypeNode ReturnTypeExpression;
+ /// <summary>Provides a way to retrieve the parameters and local variables defined in this method given their names.</summary>
+ public MethodScope Scope;
+ public bool HasOutOfBandContract = false;
+ protected TrivialHashtable/*!*/ Locals = new TrivialHashtable();
+#endif
+#if !FxCop
+ public LocalList LocalList;
+ protected SecurityAttributeList securityAttributes;
+ /// <summary>Contains declarative security information associated with the type.</summary>
+ public SecurityAttributeList SecurityAttributes
+ {
+ get
+ {
+ if (this.securityAttributes != null) return this.securityAttributes;
+ if (this.attributes == null)
+ {
+ 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
+ if (al != null) al = null;
+ if (this.securityAttributes != null) return this.securityAttributes;
+ }
+ return this.securityAttributes = new SecurityAttributeList(0);
+ }
+ set
+ {
+ this.securityAttributes = value;
+ }
+ }
+#else
+ internal SecurityAttributeList securityAttributes;
+ public SecurityAttributeList SecurityAttributes{
+ get{return this.securityAttributes;}
+ internal set{this.securityAttributes = value;}
+ }
+ private LocalCollection locals;
+ public LocalCollection Locals{
+ get{
+ if (locals == null) this.Body = this.Body;
+ return this.locals;
+ }
+ internal set {
+ this.locals = value;
+ }
+ }
+ /// <summary>
+ /// Gets a value indicating whether the method is a property or event accessor.
+ /// </summary>
+ /// <value>
+ /// <see langword="true"/> if the <see cref="Method"/> is a property or event
+ /// accessor; otherwise, <see langword="false"/>.
+ /// </value>
+ /// <remarks>
+ /// <see cref="IsAccessor"/> returns <see langword="true"/> if
+ /// <see cref="DeclaringMember"/> is not <see langword="null"/>.
+ /// </remarks>
+ public bool IsAccessor{
+ get{return this.declaringMember != null;}
+ }
+ internal static bool EnforceMethodRepresentationCreationPolicy;
+ internal static int PopulatedBodiesCount;
+ internal static int PopulatedInstructionsCount;
+#endif
+ public delegate void MethodBodyProvider(Method/*!*/ method, object/*!*/ handle, bool asInstructionList);
+ public MethodBodyProvider ProvideBody;
+ public object ProviderHandle; //Opaque information to be used by the method body provider
+ public Method()
+ : base(NodeType.Method)
+ {
+#if ExtendedRuntime
+ this.Contract = new MethodContract(this);
+#endif
+ }
+ public Method(MethodBodyProvider provider, object handle)
+ : base(NodeType.Method)
+ {
+ this.ProvideBody = provider;
+ this.ProviderHandle = handle;
+#if ExtendedRuntime
+ this.Contract = new MethodContract(this);
+#endif
+ }
+ public Method(TypeNode declaringType, AttributeList attributes, Identifier name, ParameterList parameters, TypeNode returnType, Block body)
+ : base(declaringType, attributes, name, NodeType.Method)
+ {
+ this.body = body;
+ this.Parameters = parameters; // important to use setter here.
+ this.returnType = returnType;
+#if ExtendedRuntime
+ this.Contract = new MethodContract(this);
+#endif
+ }
+ private MethodFlags flags;
+ public MethodFlags Flags
+ {
+ get { return this.flags; }
+ set { this.flags = value; }
+ }
+ private MethodImplFlags implFlags;
+ public MethodImplFlags ImplFlags
+ {
+ get { return this.implFlags; }
+ set { this.implFlags = value; }
+ }
+ private MethodList implementedInterfaceMethods;
+ public MethodList ImplementedInterfaceMethods
+ {
+ get { return this.implementedInterfaceMethods; }
+ set { this.implementedInterfaceMethods = value; }
+ }
+#if !MinimalReader
+ private MethodList implicitlyImplementedInterfaceMethods;
+ /// <summary>
+ /// Computes the implicitly implemented methods for any method, not necessarily being compiled.
+ /// </summary>
+ public MethodList ImplicitlyImplementedInterfaceMethods
+ {
+ get
+ {
+ if (this.implicitlyImplementedInterfaceMethods == null)
+ {
+ this.implicitlyImplementedInterfaceMethods = new MethodList();
+ // There are several reasons that this method cannot implicitly implement any interface method.
+ if ((this.ImplementedInterfaceMethods == null || this.ImplementedInterfaceMethods.Count == 0) && this.IsPublic && !this.IsStatic)
+ {
+ // It can implicitly implement an interface method for those interfaces that
+ // the method's type explicitly declares it implements
+ if (this.DeclaringType != null && this.DeclaringType.Interfaces != null)
+ {
+ foreach (Interface i in this.DeclaringType.Interfaces)
+ {
+ if (i == null) continue;
+ Method match = i.GetMatchingMethod(this);
+ // But it cannot implicitly implement an interface method if there is
+ // an explicit implementation in the same type.
+ if (match != null && match.ReturnType == this.ReturnType && !this.DeclaringType.ImplementsExplicitly(match))
+ this.implicitlyImplementedInterfaceMethods.Add(match);
+ }
+ }
+ // It can implicitly implement an interface method if it overrides a base class
+ // method and *that* method implicitly implements the interface method.
+ // (Note: if this method's type does *not* explicitly declare that it implements
+ // the interface, then unless the method overrides a method that does, it is *not*
+ // used as an implicit implementation.)
+ if (this.OverriddenMethod != null)
+ {
+ foreach (Method method in this.OverriddenMethod.ImplicitlyImplementedInterfaceMethods)
+ // But it cannot implicitly implement an interface method if there is
+ // an explicit implementation in the same type.
+ if (!this.DeclaringType.ImplementsExplicitly(method))
+ this.implicitlyImplementedInterfaceMethods.Add(method);
+ }
+ }
+ }
+ return this.implicitlyImplementedInterfaceMethods;
+ }
+ set
+ {
+ this.implicitlyImplementedInterfaceMethods = value;
+ }
+ }
+#endif
+ private CallingConventionFlags callingConvention;
+ public CallingConventionFlags CallingConvention
+ {
+ get { return this.callingConvention; }
+ set { this.callingConvention = value; }
+ }
+ private bool initLocals = true;
+ /// <summary>True if all local variables are to be initialized to default values before executing the method body.</summary>
+ public bool InitLocals
+ {
+ get { return this.initLocals; }
+ set { this.initLocals = value; }
+ }
+ private bool isGeneric;
+ /// <summary>True if this method is a template that conforms to the rules for a CLR generic method.</summary>
+ public bool IsGeneric
+ {
+ get { return this.isGeneric; }
+ set { this.isGeneric = value; }
+ }
+ private ParameterList parameters;
+ /// <summary>The parameters this method has to be called with.</summary>
+ public ParameterList Parameters
+ {
+ get { return this.parameters; }
+ set
+ {
+ this.parameters = value;
+ if (value != null)
+ {
+ for (int i = 0, n = value.Count; i < n; i++)
+ {
+ Parameter par = parameters[i];
+ if (par == null) continue;
+ par.DeclaringMethod = this;
+ }
+ }
+ }
+ }
+ private PInvokeFlags pInvokeFlags = PInvokeFlags.None;
+ public PInvokeFlags PInvokeFlags
+ {
+ get { return this.pInvokeFlags; }
+ set { this.pInvokeFlags = value; }
+ }
+ private Module pInvokeModule;
+ public Module PInvokeModule
+ {
+ get { return this.pInvokeModule; }
+ set { this.pInvokeModule = value; }
+ }
+ private string pInvokeImportName;
+ public string PInvokeImportName
+ {
+ get { return this.pInvokeImportName; }
+ set { this.pInvokeImportName = value; }
+ }
+ private AttributeList returnAttributes;
+ /// <summary>Attributes that apply to the return value of this method.</summary>
+ public AttributeList ReturnAttributes
+ {
+ get { return this.returnAttributes; }
+ set { this.returnAttributes = value; }
+ }
+ private MarshallingInformation returnTypeMarshallingInformation;
+ public MarshallingInformation ReturnTypeMarshallingInformation
+ {
+ get { return this.returnTypeMarshallingInformation; }
+ set { this.returnTypeMarshallingInformation = value; }
+ }
+ private TypeNode returnType;
+ /// <summary>The type of value that this method may return.</summary>
+ public TypeNode ReturnType
+ {
+ get { return this.returnType; }
+ set { this.returnType = value; }
+ }
+ private Member declaringMember;
+ /// <summary>Provides the declaring event or property of an accessor.</summary>
+ public Member DeclaringMember
+ {
+ get { return this.declaringMember; }
+ set { this.declaringMember = value; }
+ }
+ private This thisParameter;
+ public This ThisParameter
+ {
+ get
+ {
+ if (this.thisParameter == null && !this.IsStatic && this.DeclaringType != null)
+ {
+ if (this.DeclaringType.IsValueType)
+ this.ThisParameter = new This(this.DeclaringType.GetReferenceType());
+ else
+ this.ThisParameter = new This(this.DeclaringType);
+ }
+ return this.thisParameter;
+ }
+ set
+ {
+ if (value != null) value.DeclaringMethod = this;
+ this.thisParameter = value;
+ }
+ }
+ protected internal Block body;
+ /// <summary>The instructions constituting the body of this method, in the form of a tree.</summary>
+ public virtual Block Body
+ {
+ get
+ {
+ if (this.body != null) return this.body;
+ if (this.ProvideBody != null && this.ProviderHandle != null)
+ {
+ lock (Module.GlobalLock)
+ {
+ if (this.body == null)
+ {
+ this.ProvideBody(this, this.ProviderHandle, false);
+#if FxCop
+ if (EnforceMethodRepresentationCreationPolicy && this.body.Statements.Count > 0)
+ System.Threading.Interlocked.Increment(ref Method.PopulatedBodiesCount);
+#endif
+ }
+ }
+ }
+ return this.body;
+ }
+ set
+ {
+#if FxCop
+ if (EnforceMethodRepresentationCreationPolicy && value == null && this.body != null && this.body.Statements.Count > 0)
+ System.Threading.Interlocked.Decrement(ref Method.PopulatedBodiesCount);
+#endif
+ this.body = value;
+ }
+ }
+ /// <summary>
+ /// A delegate that is called the first time Attributes is accessed, if non-null.
+ /// Provides for incremental construction of the type node.
+ /// Must not leave Attributes null.
+ /// </summary>
+ public MethodAttributeProvider ProvideMethodAttributes;
+ /// <summary>
+ /// The type of delegates that fill in the Attributes property of the given method.
+ /// </summary>
+ public delegate void MethodAttributeProvider(Method/*!*/ method, object/*!*/ handle);
+ public override AttributeList Attributes
+ {
+ get
+ {
+ if (this.attributes == null)
+ {
+ if (this.ProvideMethodAttributes != null && this.ProviderHandle != null)
+ {
+ lock (Module.GlobalLock)
+ {
+ if (this.attributes == null)
+ this.ProvideMethodAttributes(this, this.ProviderHandle);
+ }
+ }
+ else
+ this.attributes = new AttributeList(0);
+ }
+ return this.attributes;
+ }
+ set
+ {
+ this.attributes = value;
+ }
+ }
+#if FxCop
+ internal void ClearBody(){
+#else
+ public void ClearBody()
+ {
+#endif
+ lock (Module.GlobalLock)
+ {
+ this.Body = null;
+ this.Instructions = null;
+#if !FxCop
+ this.LocalList = null;
+#else
+ this.Locals = null;
+#endif
+ }
+ }
+ protected string conditionalSymbol;
+ protected bool doesNotHaveAConditionalSymbol;
+ public string ConditionalSymbol
+ {
+ get
+ {
+ if (this.doesNotHaveAConditionalSymbol) return null;
+ if (this.conditionalSymbol == null)
+ {
+ lock (this)
+ {
+ if (this.conditionalSymbol != null) return this.conditionalSymbol;
+ AttributeNode condAttr = this.GetAttribute(SystemTypes.ConditionalAttribute);
+ if (condAttr != null && condAttr.Expressions != null && condAttr.Expressions.Count > 0)
+ {
+ Literal lit = condAttr.Expressions[0] as Literal;
+ if (lit != null)
+ {
+ this.conditionalSymbol = lit.Value as string;
+ if (this.conditionalSymbol != null) return this.conditionalSymbol;
+ }
+ }
+ this.doesNotHaveAConditionalSymbol = true;
+ }
+ }
+ return this.conditionalSymbol;
+ }
+ set
+ {
+ this.conditionalSymbol = value;
+ }
+ }
+ protected InstructionList instructions;
+ /// <summary>The instructions constituting the body of this method, in the form of a linear list of Instruction nodes.</summary>
+ public virtual InstructionList Instructions
+ {
+ get
+ {
+ if (this.instructions != null) return this.instructions;
+ if (this.ProvideBody != null && this.ProviderHandle != null)
+ {
+ lock (Module.GlobalLock)
+ {
+ if (this.instructions == null)
+ {
+ this.ProvideBody(this, this.ProviderHandle, true);
+#if FxCop
+ if (EnforceMethodRepresentationCreationPolicy)
+ System.Threading.Interlocked.Increment(ref Method.PopulatedInstructionsCount);
+#endif
+ }
+ }
+ }
+ return this.instructions;
+ }
+ set
+ {
+#if FxCop
+ if (EnforceMethodRepresentationCreationPolicy && this.instructions != null && value == null)
+ System.Threading.Interlocked.Decrement(ref Method.PopulatedInstructionsCount);
+#endif
+ this.instructions = value;
+ }
+ }
+#if !FxCop
+ protected ExceptionHandlerList exceptionHandlers;
+ public virtual ExceptionHandlerList ExceptionHandlers
+ {
+ get
+ {
+ if (this.exceptionHandlers != null) return this.exceptionHandlers;
+ Block dummy = this.Body;
+ if (this.exceptionHandlers == null) this.exceptionHandlers = new ExceptionHandlerList(0);
+ return this.exceptionHandlers;
+ }
+ set
+ {
+ this.exceptionHandlers = value;
+ }
+ }
+#endif
+#if !NoXml
+ protected override Identifier GetDocumentationId()
+ {
+ if (this.Template != null) return this.Template.GetDocumentationId();
+ StringBuilder sb = new StringBuilder(this.DeclaringType.DocumentationId.ToString());
+ sb[0] = 'M';
+ sb.Append('.');
+ if (this.NodeType == NodeType.InstanceInitializer)
+ sb.Append("#ctor");
+ else if (this.Name != null)
+ {
+ sb.Append(this.Name.ToString());
+ if (TargetPlatform.GenericTypeNamesMangleChar != 0 && this.TemplateParameters != null && this.TemplateParameters.Count > 0)
+ {
+ sb.Append(TargetPlatform.GenericTypeNamesMangleChar);
+ sb.Append(TargetPlatform.GenericTypeNamesMangleChar);
+ sb.Append(this.TemplateParameters.Count);
+ }
+ }
+ ParameterList parameters = this.Parameters;
+ for (int i = 0, n = parameters == null ? 0 : parameters.Count; i < n; i++)
+ {
+ Parameter par = parameters[i];
+ if (par == null || par.Type == null) continue;
+ if (i == 0)
+ sb.Append('(');
+ else
+ sb.Append(',');
+ par.Type.AppendDocumentIdMangledName(sb, this.TemplateParameters, this.DeclaringType.TemplateParameters);
+ if (i == n - 1)
+ sb.Append(')');
+ }
+ if (this.IsSpecialName && this.ReturnType != null && this.Name != null &&
+ (this.Name.UniqueIdKey == StandardIds.opExplicit.UniqueIdKey || this.Name.UniqueIdKey == StandardIds.opImplicit.UniqueIdKey))
+ {
+ sb.Append('~');
+ this.ReturnType.AppendDocumentIdMangledName(sb, this.TemplateParameters, this.DeclaringType.TemplateParameters);
+ }
+ return Identifier.For(sb.ToString());
+ }
+#endif
+ protected internal string fullName;
+ public override string/*!*/ FullName
+ {
+ get
+ {
+ if (this.fullName != null) return this.fullName;
+ StringBuilder sb = new StringBuilder();
+ if (this.DeclaringType != null)
+ {
+ sb.Append(this.DeclaringType.FullName);
+ sb.Append('.');
+ if (this.NodeType == NodeType.InstanceInitializer)
+ sb.Append("#ctor");
+ else if (this.Name != null)
+ sb.Append(this.Name.ToString());
+ ParameterList parameters = this.Parameters;
+ for (int i = 0, n = parameters == null ? 0 : parameters.Count; i < n; i++)
+ {
+ Parameter par = parameters[i];
+ if (par == null || par.Type == null) continue;
+ if (i == 0)
+ sb.Append('(');
+ else
+ sb.Append(',');
+ sb.Append(par.Type.FullName);
+ if (i == n - 1)
+ sb.Append(')');
+ }
+ }
+ return this.fullName = sb.ToString();
+ }
+ }
+#if ExtendedRuntime
+ public override string HelpText {
+ get {
+ if (this.helpText != null)
+ return this.helpText;
+ StringBuilder sb = new StringBuilder(base.HelpText);
+ // if there is already some help text, start the contract on a new line
+ bool startWithNewLine = (sb.Length != 0);
+ if (this.Contract != null){
+ MethodContract mc = this.Contract;
+ RequiresList rs = mc.Requires;
+ if (rs != null && rs.Count == 0) { mc.Requires = null; rs = mc.Requires; }
+ for (int i = 0, n = rs == null ? 0 : rs.Count; i < n; i++){
+ Requires r = rs[i];
+ Expression e = r.Condition;
+ if (e.SourceContext.StartPos < e.SourceContext.EndPos && e.SourceContext.SourceText != ""){
+ if (startWithNewLine) sb.Append('\n');
+ sb.Append("requires ");
+ sb.Append(e.SourceContext.SourceText);
+ sb.Append(";");
+ startWithNewLine = true;
+ }
+ }
+ EnsuresList es = mc.Ensures;
+ if (es != null && es.Count == 0) { mc.Ensures = null; es = mc.Ensures; }
+ if (es != null)
+ for (int i = 0, n = es.Count; i < n; i++){
+ Ensures e = es[i];
+ Expression cond = e.PostCondition;
+ if (e != null && e.SourceContext.StartPos < e.SourceContext.EndPos && e.SourceContext.SourceText != "") {
+ if (startWithNewLine) sb.Append('\n');
+ sb.Append("ensures ");
+ sb.Append(cond.SourceContext.SourceText);
+ sb.Append(";");
+ startWithNewLine = true;
+ }
+ }
+ ExpressionList exps = mc.Modifies;
+ // Force deserialization in case that is needed
+ if (exps != null && exps.Count == 0) { mc.Modifies = null; exps = mc.Modifies; }
+ if (exps != null) {
+ for (int i = 0, n = exps.Count; i < n; i++) {
+ Expression mod = exps[i];
+ if (mod != null && mod.SourceContext.StartPos < mod.SourceContext.EndPos && mod.SourceContext.SourceText != "") {
+ if (startWithNewLine) sb.Append('\n');
+ sb.Append("modifies ");
+ sb.Append(mod.SourceContext.SourceText);
+ sb.Append(";");
+ startWithNewLine = true;
+ }
+ }
+ }
+ }
+ return this.helpText = sb.ToString();
+ }
+ set {
+ base.HelpText = value;
+ }
+ }
+#endif
+ public virtual string GetUnmangledNameWithoutTypeParameters()
+ {
+ return this.GetUnmangledNameWithoutTypeParameters(false);
+ }
+ public virtual string GetUnmangledNameWithoutTypeParameters(bool omitParameterTypes)
+ {
+ StringBuilder sb = new StringBuilder();
+ if (this.NodeType == NodeType.InstanceInitializer)
+ sb.Append("#ctor");
+ else if (this.Name != null)
+ {
+ string name = this.Name.ToString();
+ int lastDot = name.LastIndexOf('.');
+ int lastMangle = name.LastIndexOf('>');
+ // explicit interface method overrides will have typenames in
+ // their method name, which may also contain type parameters
+ if (lastMangle < lastDot)
+ lastMangle = -1;
+ if (lastMangle > 0)
+ sb.Append(name.Substring(0, lastMangle + 1));
+ else
+ sb.Append(name);
+ }
+ if (omitParameterTypes) return sb.ToString();
+ ParameterList parameters = this.Parameters;
+ for (int i = 0, n = parameters == null ? 0 : parameters.Count; i < n; i++)
+ {
+ Parameter par = parameters[i];
+ if (par == null || par.Type == null) continue;
+ if (i == 0)
+ sb.Append('(');
+ else
+ sb.Append(',');
+ sb.Append(par.Type.GetFullUnmangledNameWithTypeParameters());
+ if (i == n - 1)
+ {
+#if !MinimalReader
+ if (this.IsVarArg)
+ {
+ sb.Append(", __arglist");
+ }
+#endif
+ sb.Append(')');
+ }
+ }
+ return sb.ToString();
+ }
+ public virtual string GetUnmangledNameWithTypeParameters()
+ {
+ return this.GetUnmangledNameWithTypeParameters(false);
+ }
+ public virtual string GetUnmangledNameWithTypeParameters(bool omitParameterTypes)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append(this.GetUnmangledNameWithoutTypeParameters(true));
+ TypeNodeList templateParameters = this.TemplateParameters;
+ for (int i = 0, n = templateParameters == null ? 0 : templateParameters.Count; i < n; i++)
+ {
+ TypeNode tpar = templateParameters[i];
+ if (tpar == null) continue;
+ if (i == 0)
+ sb.Append('<');
+ else
+ sb.Append(',');
+ sb.Append(tpar.Name.ToString());
+ if (i == n - 1)
+ sb.Append('>');
+ }
+ if (omitParameterTypes) return sb.ToString();
+ ParameterList parameters = this.Parameters;
+ for (int i = 0, n = parameters == null ? 0 : parameters.Count; i < n; i++)
+ {
+ Parameter par = parameters[i];
+ if (par == null || par.Type == null) continue;
+ if (i == 0)
+ sb.Append('(');
+ else
+ sb.Append(',');
+ sb.Append(par.Type.GetFullUnmangledNameWithTypeParameters());
+ if (i == n - 1)
+ sb.Append(')');
+ }
+ return sb.ToString();
+ }
+ public virtual string GetFullUnmangledNameWithTypeParameters()
+ {
+ return this.GetFullUnmangledNameWithTypeParameters(false);
+ }
+ public virtual string GetFullUnmangledNameWithTypeParameters(bool omitParameterTypes)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append(this.DeclaringType.GetFullUnmangledNameWithTypeParameters());
+ sb.Append('.');
+ sb.Append(this.GetUnmangledNameWithTypeParameters());
+ return sb.ToString();
+ }
+ public static MethodFlags GetVisibilityUnion(Method m1, Method m2)
+ {
+ if (m1 == null && m2 != null) return m2.Flags & MethodFlags.MethodAccessMask;
+ if (m2 == null && m1 != null) return m1.Flags & MethodFlags.MethodAccessMask;
+ if (m1 == null || m2 == null) return MethodFlags.CompilerControlled;
+ return Method.GetVisibilityUnion(m1.Flags, m2.Flags);
+ }
+ public static MethodFlags GetVisibilityUnion(MethodFlags vis1, MethodFlags vis2)
+ {
+ vis1 &= MethodFlags.MethodAccessMask;
+ vis2 &= MethodFlags.MethodAccessMask;
+ switch (vis1)
+ {
+ case MethodFlags.Public:
+ return MethodFlags.Public;
+ case MethodFlags.Assembly:
+ switch (vis2)
+ {
+ case MethodFlags.Public:
+ return MethodFlags.Public;
+ case MethodFlags.FamORAssem:
+ case MethodFlags.Family:
+ return MethodFlags.FamORAssem;
+ default:
+ return vis1;
+ }
+ case MethodFlags.FamANDAssem:
+ switch (vis2)
+ {
+ case MethodFlags.Public:
+ return MethodFlags.Public;
+ case MethodFlags.Assembly:
+ return MethodFlags.Assembly;
+ case MethodFlags.FamORAssem:
+ return MethodFlags.FamORAssem;
+ case MethodFlags.Family:
+ return MethodFlags.Family;
+ default:
+ return vis1;
+ }
+ case MethodFlags.FamORAssem:
+ switch (vis2)
+ {
+ case MethodFlags.Public:
+ return MethodFlags.Public;
+ default:
+ return vis1;
+ }
+ case MethodFlags.Family:
+ switch (vis2)
+ {
+ case MethodFlags.Public:
+ return MethodFlags.Public;
+ case MethodFlags.FamORAssem:
+ case MethodFlags.Assembly:
+ return MethodFlags.FamORAssem;
+ default:
+ return vis1;
+ }
+ default:
+ return vis2;
+ }
+ }
+#if !NoReflection
+ public virtual object Invoke(object targetObject, params object[] arguments)
+ {
+ System.Reflection.MethodInfo methInfo = this.GetMethodInfo();
+ if (methInfo == null) return null;
+ return methInfo.Invoke(targetObject, arguments);
+ }
+ public virtual Literal Invoke(Literal/*!*/ targetObject, params Literal[] arguments)
+ {
+ int n = arguments == null ? 0 : arguments.Length;
+ object[] args = n == 0 ? null : new object[n];
+ if (args != null && arguments != null)
+ for (int i = 0; i < n; i++)
+ {
+ Literal lit = arguments[i];
+ args[i] = lit == null ? null : lit.Value;
+ }
+ return new Literal(this.Invoke(targetObject.Value, args));
+ }
+#endif
+#if !MinimalReader
+ protected bool isNormalized;
+ public virtual bool IsNormalized
+ {
+ get
+ {
+ if (this.isNormalized) return true;
+ if (this.DeclaringType == null || this.SourceContext.Document != null) return false;
+ return this.isNormalized = this.DeclaringType.IsNormalized;
+ }
+ set
+ {
+ this.isNormalized = value;
+ }
+ }
+#endif
+ public virtual bool IsAbstract
+ {
+ get { return (this.Flags & MethodFlags.Abstract) != 0; }
+ }
+ public override bool IsAssembly
+ {
+ get { return (this.Flags & MethodFlags.MethodAccessMask) == MethodFlags.Assembly; }
+ }
+ public override bool IsCompilerControlled
+ {
+ get { return (this.Flags & MethodFlags.MethodAccessMask) == MethodFlags.CompilerControlled; }
+ }
+ public virtual bool IsExtern
+ {
+ get { return (this.Flags & MethodFlags.PInvokeImpl) != 0 || (this.ImplFlags & (MethodImplFlags.Runtime | MethodImplFlags.InternalCall)) != 0; }
+ }
+ public override bool IsFamily
+ {
+ get { return (this.Flags & MethodFlags.MethodAccessMask) == MethodFlags.Family; }
+ }
+ public override bool IsFamilyAndAssembly
+ {
+ get { return (this.Flags & MethodFlags.MethodAccessMask) == MethodFlags.FamANDAssem; }
+ }
+ public override bool IsFamilyOrAssembly
+ {
+ get { return (this.Flags & MethodFlags.MethodAccessMask) == MethodFlags.FamORAssem; }
+ }
+ public virtual bool IsFinal
+ {
+ get { return (this.Flags & MethodFlags.Final) != 0; }
+ }
+#if !MinimalReader
+ public virtual bool IsInternalCall
+ {
+ get { return (this.ImplFlags & MethodImplFlags.InternalCall) != 0; }
+ }
+#endif
+ public override bool IsPrivate
+ {
+ get { return (this.Flags & MethodFlags.MethodAccessMask) == MethodFlags.Private; }
+ }
+ public override bool IsPublic
+ {
+ get { return (this.Flags & MethodFlags.MethodAccessMask) == MethodFlags.Public; }
+ }
+ public override bool IsSpecialName
+ {
+ get { return (this.Flags & MethodFlags.SpecialName) != 0; }
+ }
+ public override bool IsStatic
+ {
+ get { return (this.Flags & MethodFlags.Static) != 0; }
+ }
+ /// <summary>
+ /// True if this method can in principle be overridden by a method in a derived class.
+ /// </summary>
+ public virtual bool IsVirtual
+ {
+ get { return (this.Flags & MethodFlags.Virtual) != 0; }
+ }
+#if !MinimalReader
+ public virtual bool IsNonSealedVirtual
+ {
+ get
+ {
+ return (this.Flags & MethodFlags.Virtual) != 0 && (this.Flags & MethodFlags.Final) == 0 &&
+ (this.DeclaringType == null || (this.DeclaringType.Flags & TypeFlags.Sealed) == 0);
+ }
+ }
+ public virtual bool IsVirtualAndNotDeclaredInStruct
+ {
+ get
+ {
+ return (this.Flags & MethodFlags.Virtual) != 0 && (this.DeclaringType == null || !(this.DeclaringType is Struct));
+ }
+ }
+#endif
+ public override bool IsVisibleOutsideAssembly
+ {
+ get
+ {
+ if (this.DeclaringType != null && !this.DeclaringType.IsVisibleOutsideAssembly) return false;
+ switch (this.Flags & MethodFlags.MethodAccessMask)
+ {
+ case MethodFlags.Public:
+ return true;
+ case MethodFlags.Family:
+ case MethodFlags.FamORAssem:
+ if (this.DeclaringType != null && !this.DeclaringType.IsSealed) return true;
+ goto default;
+ default:
+ for (int i = 0, n = this.ImplementedInterfaceMethods == null ? 0 : this.ImplementedInterfaceMethods.Count; i < n; i++)
+ {
+ Method m = this.ImplementedInterfaceMethods[i];
+ if (m == null) continue;
+ if (m.DeclaringType != null && !m.DeclaringType.IsVisibleOutsideAssembly) continue;
+ if (m.IsVisibleOutsideAssembly) return true;
+ }
+ return false;
+ }
+ }
+ }
+#if ExtendedRuntime
+ public bool IsPure{
+ get{
+ return this.GetAttribute(SystemTypes.PureAttribute) != null;
+ }
+ }
+ public bool ApplyDefaultActivity {
+ get {
+ return this.GetAttribute(SystemTypes.NoDefaultActivityAttribute) == null;
+ }
+ }
+ public bool ApplyDefaultContract {
+ get{
+ return this.GetAttribute(SystemTypes.NoDefaultContractAttribute) == null;
+ }
+ }
+ public bool IsPropertyGetter{
+ get{
+ if (this.DeclaringMember == null) return false;
+ Property p = this.DeclaringMember as Property;
+ if (p == null) return false;
+ if (p.Getter == this) return true;
+ if (this.Template != null) {
+ p = this.Template.DeclaringMember as Property;
+ if (p != null) return p.Getter == this.Template;
+ }
+ return false;
+ }
+ }
+ public bool IsPropertySetter {
+ get {
+ if (this.DeclaringMember == null) return false;
+ Property p = this.DeclaringMember as Property;
+ if (p == null) return false;
+ if (p.Setter == this) return true;
+ if (this.Template != null) {
+ p = this.Template.DeclaringMember as Property;
+ if (p != null) return p.Setter == this.Template;
+ }
+ return false;
+ }
+ }
+ public bool IsConfined {
+ get{
+ return this.ApplyDefaultContract && this.IsPropertyGetter && !(this.DeclaringType is Struct) || this.GetAttribute(SystemTypes.ConfinedAttribute) != null;
+ }
+ }
+ public bool IsWriteConfined {
+ get {
+ return this.GetAttribute(SystemTypes.WriteConfinedAttribute) != null
+ || IsConfined || IsStateIndependent;
+ }
+ }
+ public bool IsStateIndependent{
+ get{
+ return this.ApplyDefaultContract && this.IsPropertyGetter && this.DeclaringType is Struct || this.GetAttribute(SystemTypes.StateIndependentAttribute) != null;
+ }
+ }
+#endif
+#if !MinimalReader
+ public bool IsVarArg
+ {
+ get { return (this.CallingConvention & CallingConventionFlags.VarArg) != 0; }
+ }
+ // whether this is a FieldInitializerMethod (declared in Sing#)
+ public virtual bool IsFieldInitializerMethod
+ {
+ get
+ {
+ return false;
+ }
+ }
+#endif
+ public override Member HiddenMember
+ {
+ get
+ {
+ return this.HiddenMethod;
+ }
+ set
+ {
+ this.HiddenMethod = (Method)value;
+ }
+ }
+ public virtual Method HiddenMethod
+ {
+ get
+ {
+ if (this.hiddenMember == Method.NotSpecified) return null;
+ Method hiddenMethod = this.hiddenMember as Method;
+ if (hiddenMethod != null) return hiddenMethod;
+ if (this.ProvideBody == null) return null;
+ if (this.IsVirtual && (this.Flags & MethodFlags.VtableLayoutMask) != MethodFlags.NewSlot) return null;
+ TypeNode baseType = this.DeclaringType.BaseType;
+ while (baseType != null)
+ {
+ MemberList baseMembers = baseType.GetMembersNamed(this.Name);
+ if (baseMembers != null)
+ for (int i = 0, n = baseMembers.Count; i < n; i++)
+ {
+ Method bmeth = baseMembers[i] as Method;
+ if (bmeth == null) continue;
+ if (!bmeth.ParametersMatch(this.Parameters))
+ {
+ if (this.TemplateParameters != null && this.TemplateParametersMatch(bmeth.TemplateParameters))
+ {
+ if (!bmeth.ParametersMatchStructurally(this.Parameters)) continue;
+ }
+ else
+ continue;
+ }
+ hiddenMethod = bmeth;
+ goto done;
+ }
+ baseType = baseType.BaseType;
+ }
+ done:
+ if (hiddenMethod == null)
+ {
+ this.hiddenMember = Method.NotSpecified;
+ return null;
+ }
+ this.hiddenMember = hiddenMethod;
+ return hiddenMethod;
+ }
+ set
+ {
+ this.hiddenMember = value;
+ }
+ }
+ public override Member OverriddenMember
+ {
+ get
+ {
+ return this.OverriddenMethod;
+ }
+ set
+ {
+ this.OverriddenMethod = (Method)value;
+ }
+ }
+ public virtual Method OverriddenMethod
+ {
+ get
+ {
+ if ((this.Flags & MethodFlags.VtableLayoutMask) == MethodFlags.NewSlot) return null;
+ if (this.overriddenMember == Method.NotSpecified) return null;
+ Method overriddenMethod = this.overriddenMember as Method;
+ if (overriddenMethod != null) return overriddenMethod;
+ if (this.ProvideBody == null) return null;
+ if (!this.IsVirtual) return null;
+ TypeNode baseType = this.DeclaringType.BaseType;
+ while (baseType != null)
+ {
+ MemberList baseMembers = baseType.GetMembersNamed(this.Name);
+ if (baseMembers != null)
+ for (int i = 0, n = baseMembers.Count; i < n; i++)
+ {
+ Method bmeth = baseMembers[i] as Method;
+ if (bmeth == null) continue;
+ if (!bmeth.ParametersMatch(this.Parameters))
+ {
+ if (this.TemplateParameters != null && this.TemplateParametersMatch(bmeth.TemplateParameters))
+ {
+ if (!bmeth.ParametersMatchStructurally(this.Parameters)) continue;
+ }
+ else
+ continue;
+ }
+ overriddenMethod = bmeth;
+ goto done;
+ }
+ baseType = baseType.BaseType;
+ }
+ done:
+ if (overriddenMethod == null)
+ {
+ this.overriddenMember = Method.NotSpecified;
+ return null;
+ }
+ this.overriddenMember = overriddenMethod;
+ return overriddenMethod;
+ }
+ set
+ {
+ this.overriddenMember = value;
+ }
+ }
+#if !NoReflection
+ public static Method GetMethod(System.Reflection.MethodInfo methodInfo)
+ {
+ if (methodInfo == null) return null;
+#if WHIDBEY
+ if (methodInfo.IsGenericMethod && !methodInfo.IsGenericMethodDefinition)
+ {
+ try
+ {
+ Method template = Method.GetMethod(methodInfo.GetGenericMethodDefinition());
+ if (template == null) return null;
+ TypeNodeList templateArguments = new TypeNodeList();
+ foreach (Type arg in methodInfo.GetGenericArguments())
+ templateArguments.Add(TypeNode.GetTypeNode(arg));
+ return template.GetTemplateInstance(template.DeclaringType, templateArguments);
+ }
+ catch
+ {
+ //TODO: log error
+ return null;
+ }
+ }
+#endif
+ TypeNode tn = TypeNode.GetTypeNode(methodInfo.DeclaringType);
+ if (tn == null) return null;
+ System.Reflection.ParameterInfo[] paramInfos = methodInfo.GetParameters();
+ int n = paramInfos == null ? 0 : paramInfos.Length;
+ TypeNode[] parameterTypes = new TypeNode[n];
+ for (int i = 0; i < n; i++)
+ {
+ System.Reflection.ParameterInfo param = paramInfos[i];
+ if (param == null) return null;
+ parameterTypes[i] = TypeNode.GetTypeNode(param.ParameterType);
+ }
+ TypeNodeList paramTypes = new TypeNodeList(parameterTypes);
+ TypeNode returnType = TypeNode.GetTypeNode(methodInfo.ReturnType);
+ MemberList members = tn.GetMembersNamed(Identifier.For(methodInfo.Name));
+ for (int i = 0, m = members == null ? 0 : members.Count; i < m; i++)
+ {
+ Method meth = members[i] as Method;
+ if (meth == null) continue;
+ if (!meth.ParameterTypesMatch(paramTypes)) continue;
+ if (meth.ReturnType != returnType) continue;
+ return meth;
+ }
+ return null;
+ }
+#endif
+#if !NoReflection && !MinimalReader && WHIDBEY
+ protected System.Reflection.Emit.DynamicMethod dynamicMethod;
+ public virtual System.Reflection.Emit.DynamicMethod GetDynamicMethod()
+ {
+ return this.GetDynamicMethod(false);
+ }
+ public virtual System.Reflection.Emit.DynamicMethod GetDynamicMethod(bool skipVisibility)
+ //^ requires this.DeclaringType != null && this.DeclaringType.DeclaringModule != null && this.IsNormalized && this.Name != null && this.ReturnType != null;
+ //^ requires (this.CallingConvention & CallingConventionFlags.ArgumentConvention) == CallingConventionFlags.StandardCall;
+ //^ requires !this.IsGeneric;
+ {
+ if (this.dynamicMethod == null)
+ {
+ if (this.DeclaringType == null || this.DeclaringType.DeclaringModule == null || !this.IsNormalized || this.Name == null || this.ReturnType == null)
+ {
+ Debug.Assert(false); return null;
+ }
+ if ((this.CallingConvention & CallingConventionFlags.ArgumentConvention) != CallingConventionFlags.StandardCall || this.IsGeneric)
+ {
+ Debug.Assert(false); return null;
+ }
+ string name = this.Name.Name;
+ System.Reflection.MethodAttributes attrs = (System.Reflection.MethodAttributes)this.Flags;
+ System.Reflection.CallingConventions callConv = System.Reflection.CallingConventions.Standard;
+ callConv |= (System.Reflection.CallingConventions)(this.CallingConvention & ~CallingConventionFlags.ArgumentConvention);
+ System.Type rtype = this.ReturnType.GetRuntimeType();
+ System.Type owner = this.DeclaringType.GetRuntimeType();
+ if (owner == null) { Debug.Fail(""); return null; }
+ System.Reflection.Module module = owner.Module;
+ System.Reflection.Emit.DynamicMethod dmeth;
+ int numPars = this.Parameters == null ? 0 : this.Parameters.Count;
+ System.Type[] paramTypes = new Type[numPars];
+ for (int i = 0; i < numPars; i++)
+ {
+ Parameter par = this.Parameters[i];
+ if (par == null || par.Type == null) { Debug.Assert(false); return null; }
+ paramTypes[i] = par.Type.GetRuntimeType();
+ }
+ if (this.DeclaringType == this.DeclaringType.DeclaringModule.Types[0])
+ dmeth = new System.Reflection.Emit.DynamicMethod(name, attrs, callConv, rtype, paramTypes, module, skipVisibility);
+ else
+ dmeth = new System.Reflection.Emit.DynamicMethod(name, attrs, callConv, rtype, paramTypes, owner, skipVisibility);
+ dmeth.InitLocals = true;
+ ReGenerator reGenerator = new ReGenerator(dmeth.GetILGenerator());
+ reGenerator.VisitMethod(this);
+ }
+ return this.dynamicMethod;
+ }
+#endif
+#if !NoReflection
+ protected System.Reflection.MethodInfo methodInfo;
+ public virtual System.Reflection.MethodInfo GetMethodInfo()
+ {
+ if (this.methodInfo == null)
+ {
+ if (this.DeclaringType == null) return null;
+#if WHIDBEY
+ if (this.IsGeneric && this.Template != null)
+ {
+ try
+ {
+ System.Reflection.MethodInfo templateInfo = this.Template.GetMethodInfo();
+ if (templateInfo == null) return null;
+ TypeNodeList args = this.TemplateArguments;
+ Type[] arguments = new Type[args.Count];
+ for (int i = 0; i < args.Count; i++) arguments[i] = args[i].GetRuntimeType();
+ return templateInfo.MakeGenericMethod(arguments);
+ }
+ catch
+ {
+ //TODO: log error
+ return null;
+ }
+ }
+#endif
+ Type t = this.DeclaringType.GetRuntimeType();
+ if (t == null) return null;
+ Type retType = typeof(object);
+ if (!this.isGeneric)
+ {
+ //Can't do this for generic methods since it may involve a method type parameter
+ retType = this.ReturnType.GetRuntimeType();
+ if (retType == null) return null;
+ }
+ ParameterList pars = this.Parameters;
+ int n = pars == null ? 0 : pars.Count;
+ Type[] types = new Type[n];
+ for (int i = 0; i < n; i++)
+ {
+ Parameter p = pars[i];
+ if (p == null || p.Type == null) return null;
+ Type pt;
+ if (this.isGeneric)
+ 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
+ //unless we already have the method info in hand
+ else
+ pt = types[i] = p.Type.GetRuntimeType();
+ if (pt == null) return null;
+ }
+ System.Reflection.MemberInfo[] members = t.GetMember(this.Name.ToString(), System.Reflection.MemberTypes.Method,
+ BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
+ foreach (System.Reflection.MethodInfo meth in members)
+ {
+ if (meth == null) continue;
+ if (meth.IsStatic != this.IsStatic) continue;
+ if (meth.ReturnType != retType) continue;
+#if WHIDBEY
+ if (meth.IsGenericMethodDefinition)
+ {
+ TypeNodeList templateParams = this.TemplateParameters;
+ Type[] genericArgs = meth.GetGenericArguments();
+ if (templateParams == null || genericArgs == null || templateParameters.Count != genericArgs.Length) goto tryNext;
+ for (int i = 0, m = genericArgs.Length; i < m; i++)
+ {
+ TypeNode t1 = templateParameters[i];
+ Type t2 = genericArgs[i];
+ if (t1 == null || t2 == null || t1.Name == null || t1.Name.Name != t2.Name) goto tryNext;
+ }
+ }
+#endif
+ System.Reflection.ParameterInfo[] parameters = meth.GetParameters();
+ int parCount = parameters == null ? 0 : parameters.Length;
+ if (parCount != n) continue;
+ for (int i = 0; i < n; i++)
+ {
+ //^ assert parameters != null;
+ System.Reflection.ParameterInfo par = parameters[i];
+ if (par == null) goto tryNext;
+ if (this.isGeneric)
+ {
+ //We don't have the runtime type for the parameter, so just check that the name is the same
+ Parameter p = pars[i];
+ if (par.Name != p.Name.Name) goto tryNext;
+ }
+ else
+ {
+ if (par.ParameterType != types[i]) goto tryNext;
+ }
+ }
+ return this.methodInfo = meth;
+ tryNext: ;
+ }
+ }
+ return this.methodInfo;
+ }
+#endif
+#if !MinimalReader
+ protected TypeNode[] parameterTypes;
+ public virtual TypeNode[]/*!*/ GetParameterTypes()
+ {
+ if (this.parameterTypes != null) return this.parameterTypes;
+ ParameterList pars = this.Parameters;
+ int n = pars == null ? 0 : pars.Count;
+ TypeNode[] types = this.parameterTypes = new TypeNode[n];
+ for (int i = 0; i < n; i++)
+ {
+ Parameter p = pars[i];
+ if (p == null) continue;
+ types[i] = p.Type;
+ }
+ return types;
+ }
+#endif
+ public virtual bool ParametersMatch(ParameterList parameters)
+ {
+ ParameterList pars = this.Parameters;
+ int n = pars == null ? 0 : pars.Count;
+ int m = parameters == null ? 0 : parameters.Count;
+ if (n != m) return false;
+ if (parameters == null) return true;
+ for (int i = 0; i < n; i++)
+ {
+ Parameter par1 = pars[i];
+ Parameter par2 = parameters[i];
+ if (par1 == null || par2 == null) return false;
+ if (par1.Type != par2.Type) return false;
+ }
+ return true;
+ }
+#if !MinimalReader
+ public virtual bool ParametersMatchExceptLast(ParameterList parameters)
+ {
+ ParameterList pars = this.Parameters;
+ int n = pars == null ? 0 : pars.Count;
+ int m = parameters == null ? 0 : parameters.Count;
+ if (n != m) return false;
+ if (parameters == null) return true;
+ for (int i = 0; i < n - 1; i++)
+ {
+ Parameter par1 = pars[i];
+ Parameter par2 = parameters[i];
+ if (par1 == null || par2 == null) return false;
+ if (par1.Type != par2.Type) return false;
+ }
+ return true;
+ }
+#endif
+ public virtual bool ParametersMatchStructurally(ParameterList parameters)
+ {
+ ParameterList pars = this.Parameters;
+ int n = pars == null ? 0 : pars.Count;
+ int m = parameters == null ? 0 : parameters.Count;
+ if (n != m) return false;
+ if (parameters == null) return true;
+ for (int i = 0; i < n; i++)
+ {
+ Parameter par1 = pars[i];
+ Parameter par2 = parameters[i];
+ if (par1 == null || par2 == null) return false;
+ if (par1.Type == null || par2.Type == null) return false;
+ if (par1.Type != par2.Type && !par1.Type.IsStructurallyEquivalentTo(par2.Type)) return false;
+ }
+ return true;
+ }
+#if !MinimalReader
+ public virtual bool ParametersMatchStructurallyIncludingOutFlag(ParameterList parameters)
+ {
+ return this.ParametersMatchStructurallyIncludingOutFlag(parameters, false);
+ }
+ public virtual bool ParametersMatchStructurallyIncludingOutFlag(ParameterList parameters, bool allowCoVariance)
+ {
+ ParameterList pars = this.Parameters;
+ int n = pars == null ? 0 : pars.Count;
+ int m = parameters == null ? 0 : parameters.Count;
+ if (n != m) return false;
+ if (parameters == null) return true;
+ for (int i = 0; i < n; i++)
+ {
+ Parameter par1 = pars[i];
+ Parameter par2 = parameters[i];
+ if (par1 == null || par2 == null) return false;
+ if (par1.Type == null || par2.Type == null) return false;
+ if ((par1.Flags & ParameterFlags.Out) != (par2.Flags & ParameterFlags.Out)) return false;
+ if (par1.Type != par2.Type && !par1.Type.IsStructurallyEquivalentTo(par2.Type))
+ {
+ if (allowCoVariance && !par2.Type.IsValueType) return par2.Type.IsAssignableTo(par1.Type);
+ return false;
+ }
+ }
+ return true;
+ }
+ public virtual bool ParametersMatchStructurallyExceptLast(ParameterList parameters)
+ {
+ ParameterList pars = this.Parameters;
+ int n = pars == null ? 0 : pars.Count;
+ int m = parameters == null ? 0 : parameters.Count;
+ if (n != m) return false;
+ if (parameters == null) return true;
+ for (int i = 0; i < n - 1; i++)
+ {
+ Parameter par1 = pars[i];
+ Parameter par2 = parameters[i];
+ if (par1 == null || par2 == null) return false;
+ if (par1.Type == null || par2.Type == null) return false;
+ if (par1.Type != par2.Type && !par1.Type.IsStructurallyEquivalentTo(par2.Type)) return false;
+ }
+ return true;
+ }
+ public virtual bool ParametersMatchIncludingOutFlag(ParameterList parameters)
+ {
+ ParameterList pars = this.Parameters;
+ int n = pars == null ? 0 : pars.Count;
+ int m = parameters == null ? 0 : parameters.Count;
+ if (n != m) return false;
+ if (parameters == null) return true;
+ for (int i = 0; i < n; i++)
+ {
+ Parameter par1 = pars[i];
+ Parameter par2 = parameters[i];
+ if (par1.Type != par2.Type) return false;
+ if ((par1.Flags & ParameterFlags.Out) != (par2.Flags & ParameterFlags.Out)) return false;
+ }
+ return true;
+ }
+#endif
+ public virtual bool ParameterTypesMatch(TypeNodeList argumentTypes)
+ {
+ int n = this.Parameters == null ? 0 : this.Parameters.Count;
+ int m = argumentTypes == null ? 0 : argumentTypes.Count;
+ if (n != m) return false;
+ if (argumentTypes == null) return true;
+ for (int i = 0; i < n; i++)
+ {
+ Parameter par = this.Parameters[i];
+ if (par == null) return false;
+ TypeNode argType = argumentTypes[i];
+ if (par.Type != argType)
+ {
+ TypeNode pType = TypeNode.StripModifiers(par.Type);
+ argType = TypeNode.StripModifiers(argType);
+ if (pType != argType) return false;
+ }
+ }
+ return true;
+ }
+ public virtual bool ParameterTypesMatchStructurally(TypeNodeList argumentTypes)
+ {
+ int n = this.Parameters == null ? 0 : this.Parameters.Count;
+ int m = argumentTypes == null ? 0 : argumentTypes.Count;
+ if (n != m) return false;
+ if (argumentTypes == null) return true;
+ for (int i = 0; i < n; i++)
+ {
+ Parameter par = this.Parameters[i];
+ TypeNode argType = argumentTypes[i];
+ if (par.Type != argType)
+ {
+ TypeNode pType = TypeNode.StripModifiers(par.Type);
+ argType = TypeNode.StripModifiers(argType);
+ if (pType == null || !pType.IsStructurallyEquivalentTo(argType)) return false;
+ }
+ }
+ return true;
+ }
+ public virtual bool TemplateParametersMatch(TypeNodeList templateParameters)
+ {
+ TypeNodeList locPars = this.TemplateParameters;
+ if (locPars == null) return templateParameters == null || templateParameters.Count == 0;
+ if (templateParameters == null) return false;
+ int n = locPars.Count;
+ if (n != templateParameters.Count) return false;
+ for (int i = 0; i < n; i++)
+ {
+ TypeNode tp1 = locPars[i];
+ TypeNode tp2 = templateParameters[i];
+ if (tp1 == null || tp2 == null) return false;
+ if (tp1 != tp2 && !tp1.IsStructurallyEquivalentTo(tp2)) return false;
+ }
+ return true;
+ }
+#if UseSingularityPDB
+ internal TrivialHashtable contextForOffset;
+ internal void RecordSequencePoints(PdbFunction methodInfo) {
+ if (methodInfo == null || this.contextForOffset != null) return;
+ this.contextForOffset = new TrivialHashtable();
+ for (int i = 0, n = methodInfo.lines == null ? 0 : methodInfo.lines.Length; i < n; i++) {
+ PdbLines lines = methodInfo.lines[i];
+ PdbDocument doc = new PdbDocument(lines);
+ for (int j = 0, m = lines.lines.Length; j < m; j++) {
+ PdbLine line = lines.lines[j];
+ if (line.line != 0xfeefee)
+ this.contextForOffset[(int)line.offset+1] = new SourceContext(doc, j*2, j*2+1 );
+ }
+ }
+ }
+#elif !ROTOR
+ internal TrivialHashtable contextForOffset;
+ internal void RecordSequencePoints(ISymUnmanagedMethod methodInfo)
+ {
+ if (methodInfo == null || this.contextForOffset != null) return;
+ this.contextForOffset = new TrivialHashtable();
+ uint count = methodInfo.GetSequencePointCount();
+ IntPtr[] docPtrs = new IntPtr[count];
+ uint[] startLines = new uint[count];
+ uint[] startCols = new uint[count];
+ uint[] endLines = new uint[count];
+ uint[] endCols = new uint[count];
+ uint[] offsets = new uint[count];
+ uint numPoints;
+ methodInfo.GetSequencePoints(count, out numPoints, offsets, docPtrs, startLines, startCols, endLines, endCols);
+ Debug.Assert(count == numPoints);
+ for (int i = 0; i < count; i++)
+ {
+ //The magic hex constant below works around weird data reported from GetSequencePoints.
+ //The constant comes from ILDASM's source code, which performs essentially the same test.
+ const uint Magic = 0xFEEFEE;
+ if (startLines[i] >= Magic || endLines[i] >= Magic) continue;
+ UnmanagedDocument doc = new UnmanagedDocument(docPtrs[i]);
+ this.contextForOffset[(int)offsets[i] + 1] =
+#if !FxCop
+ new SourceContext(doc, doc.GetOffset(startLines[i], startCols[i]), doc.GetOffset(endLines[i], endCols[i]));
+#else
+ new SourceContext(doc.Name, startLines[i], endLines[i], startCols[i], endCols[i]);
+#endif
+ }
+ for (int i = 0; i < count; i++)
+ System.Runtime.InteropServices.Marshal.Release(docPtrs[i]);
+ }
+#endif
+ private static Method NotSpecified = new Method();
+ private Method template;
+ /// <summary>The (generic) method template from which this method was instantiated. Null if this is not a (generic) method template instance.</summary>
+ public Method Template
+ {
+ get
+ {
+ Method result = this.template;
+#if ExtendedRuntime
+ if (result == null){
+ AttributeList attributes = this.Attributes;
+ lock(this){
+ if (this.template != null) return this.template;
+ for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++){
+ AttributeNode attr = attributes[i];
+ if (attr == null) continue;
+ MemberBinding mb = attr.Constructor as MemberBinding;
+ if (mb == null || mb.BoundMember == null || mb.BoundMember.DeclaringType != SystemTypes.TemplateInstanceAttribute) continue;
+ ExpressionList exprs = attr.Expressions;
+ if (exprs == null || exprs.Count != 2) continue;
+ Literal lit = exprs[0] as Literal;
+ if (lit == null) continue;
+ TypeNode templ = lit.Value as TypeNode;
+ if (templ != null){
+ lit = exprs[1] as Literal;
+ if (lit == null) continue;
+ object[] types = lit.Value as object[];
+ if (types == null) continue;
+ int m = types == null ? 0 : types.Length;
+ TypeNodeList templateArguments = new TypeNodeList(m);
+ for (int j = 0; j < m; j++){
+ //^ assert types != null;
+ TypeNode t = types[j] as TypeNode;
+ if (t == null) continue;
+ templateArguments.Add(t);
+ }
+ this.TemplateArguments = templateArguments;
+ MemberList members = templ.GetMembersNamed(this.Name);
+ if (members != null)
+ for (int j = 0, k = members.Count; j < k; j++){
+ Method meth = members[j] as Method;
+ if (meth == null) continue;
+ if (meth.ParametersMatch(this.Parameters)){
+ this.template = result = meth; break;
+ }
+ }
+ }
+ }
+ if (result == null)
+ this.template = Method.NotSpecified;
+ }
+ }else
+#endif
+ if (result == Method.NotSpecified)
+ return null;
+ return result;
+ }
+ set
+ {
+ this.template = value;
+ }
+ }
+ private TypeNodeList templateArguments;
+ /// <summary>
+ /// The arguments used when this (generic) method template instance was instantiated.
+ /// </summary>
+ public TypeNodeList TemplateArguments
+ {
+ get { return this.templateArguments; }
+ set { this.templateArguments = value; }
+ }
+ internal TypeNodeList templateParameters;
+ public virtual TypeNodeList TemplateParameters
+ {
+ get
+ {
+ TypeNodeList result = this.templateParameters;
+#if ExtendedRuntime
+ if (result == null && this.Template == null){
+ this.TemplateParameters = result = new TypeNodeList();
+ AttributeList attributes = this.Attributes;
+ for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++){
+ AttributeNode attr = attributes[i];
+ if (attr == null) continue;
+ MemberBinding mb = attr.Constructor as MemberBinding;
+ if (mb == null || mb.BoundMember == null || mb.BoundMember.DeclaringType != SystemTypes.TemplateAttribute) continue;
+ ExpressionList exprs = attr.Expressions;
+ if (exprs == null || exprs.Count != 1) continue;
+ Literal lit = exprs[0] as Literal;
+ if (lit == null) continue;
+ object[] types = lit.Value as object[];
+ if (types == null) continue;
+ for (int j = 0, m = types == null ? 0 : types.Length; j < m; j++){
+ TypeNode t = types[j] as TypeNode;
+ if (t == null) continue;
+ if (t.NodeType == NodeType.TypeParameter || t.NodeType == NodeType.ClassParameter)
+ result.Add(t);
+ }
+ attributes[i] = null;
+ }
+ }
+ if (result == null || result.Count == 0) return null;
+#endif
+ return result;
+ }
+ set
+ {
+ this.templateParameters = value;
+ }
+ }
+ public virtual Method/*!*/ GetTemplateInstance(TypeNode referringType, params TypeNode[] typeArguments)
+ {
+ return this.GetTemplateInstance(referringType, new TypeNodeList(typeArguments));
+ }
+ public virtual Method/*!*/ GetTemplateInstance(TypeNode referringType, TypeNodeList typeArguments)
+ {
+ if (referringType == null || this.DeclaringType == null) { Debug.Assert(false); return this; }
+ if (this.IsGeneric) referringType = this.DeclaringType;
+ if (referringType != this.DeclaringType && referringType.DeclaringModule == this.DeclaringType.DeclaringModule)
+ return this.GetTemplateInstance(this.DeclaringType, typeArguments);
+ if (referringType.structurallyEquivalentMethod == null)
+ referringType.structurallyEquivalentMethod = new TrivialHashtableUsingWeakReferences();
+ Module module = referringType.DeclaringModule;
+ if (module == null) return this;
+ int n = typeArguments == null ? 0 : typeArguments.Count;
+ if (n == 0 || typeArguments == null) return this;
+ StringBuilder sb = new StringBuilder(this.Name.ToString());
+ sb.Append('<');
+ for (int i = 0; i < n; i++)
+ {
+ TypeNode ta = typeArguments[i]; if (ta == null) continue;
+ sb.Append(ta.FullName);
+ if (i < n - 1) sb.Append(',');
+ }
+ sb.Append('>');
+ Identifier mangledName = Identifier.For(sb.ToString());
+ lock (this)
+ {
+ Method m = (Method)referringType.structurallyEquivalentMethod[mangledName.UniqueIdKey];
+ int counter = 1;
+ while (m != null)
+ {
+ if (m.template == this && Method.TypeListsAreEquivalent(m.TemplateArguments, typeArguments))
+ return m;
+ mangledName = Identifier.For(mangledName.ToString() + counter++);
+ m = (Method)referringType.structurallyEquivalentMethod[mangledName.UniqueIdKey];
+ }
+ Duplicator duplicator = new Duplicator(referringType.DeclaringModule, referringType);
+ duplicator.RecordOriginalAsTemplate = true;
+ duplicator.SkipBodies = true;
+ Method result = duplicator.VisitMethod(this);
+ //^ assume result != null;
+ result.Attributes = this.Attributes; //These do not get specialized, but may need to get normalized
+ result.Name = mangledName;
+ result.fullName = null;
+ result.template = this;
+ result.TemplateArguments = typeArguments;
+ TypeNodeList templateParameters = result.TemplateParameters;
+ result.TemplateParameters = null;
+#if !MinimalReader
+ result.IsNormalized = true;
+#endif
+ if (!this.IsGeneric)
+ {
+ ParameterList pars = this.Parameters;
+ ParameterList rpars = result.Parameters;
+ if (pars != null && rpars != null && rpars.Count >= pars.Count)
+ for (int i = 0, count = pars.Count; i < count; i++)
+ {
+ Parameter p = pars[i];
+ Parameter rp = rpars[i];
+ if (p == null || rp == null) continue;
+ rp.Attributes = p.Attributes; //These do not get specialized, but may need to get normalized
+ }
+ }
+ if (!this.IsGeneric && !(result.IsStatic) && this.DeclaringType != referringType)
+ {
+ result.Flags &= ~(MethodFlags.Virtual | MethodFlags.NewSlot);
+ result.Flags |= MethodFlags.Static;
+ result.CallingConvention &= ~CallingConventionFlags.HasThis;
+ result.CallingConvention |= CallingConventionFlags.ExplicitThis;
+ ParameterList pars = result.Parameters;
+ if (pars == null) result.Parameters = pars = new ParameterList(1);
+ Parameter thisPar = new Parameter(StandardIds.This, this.DeclaringType);
+ pars.Add(thisPar);
+ for (int i = pars.Count - 1; i > 0; i--)
+ pars[i] = pars[i - 1];
+ pars[0] = thisPar;
+ }
+ referringType.structurallyEquivalentMethod[mangledName.UniqueIdKey] = result;
+ Specializer specializer = new Specializer(module, templateParameters, typeArguments);
+ specializer.VisitMethod(result);
+ if (this.IsGeneric) { result.DeclaringType = this.DeclaringType; return result; }
+ if (this.IsAbstract) return result;
+ referringType.Members.Add(result);
+ return result;
+ }
+ }
+ private static bool TypeListsAreEquivalent(TypeNodeList list1, TypeNodeList list2)
+ {
+ if (list1 == null || list2 == null) return list1 == list2;
+ int n = list1.Count;
+ if (n != list2.Count) return false;
+ for (int i = 0; i < n; i++)
+ if (list1[i] != list2[i]) return false;
+ return true;
+ }
+#if !MinimalReader
+ /// <summary>
+ /// Returns the local associated with the given field, allocating a new local if necessary.
+ /// </summary>
+ public virtual Local/*!*/ GetLocalForField(Field/*!*/ f)
+ {
+ Local loc = (Local)this.Locals[f.UniqueKey];
+ if (loc == null)
+ {
+ this.Locals[f.UniqueKey] = loc = new Local(f.Name, f.Type);
+ loc.SourceContext = f.Name.SourceContext;
+ }
+ return loc;
+ }
+#endif
+ //TODO: Also need to add a method for allocating locals
+ public Method CreateExplicitImplementation(TypeNode implementingType, ParameterList parameters, StatementList body)
+ {
+ Method m = new Method(implementingType, null, this.Name, parameters, this.ReturnType, new Block(body));
+ m.CallingConvention = CallingConventionFlags.HasThis;
+ m.Flags = MethodFlags.Public | MethodFlags.HideBySig | MethodFlags.Virtual | MethodFlags.NewSlot | MethodFlags.Final;
+ m.ImplementedInterfaceMethods = new MethodList(this);
+ //m.ImplementedTypes = new TypeNodeList(this.DeclaringType);
+ return m;
+ }
+
+ public virtual bool TypeParameterCountsMatch(Method meth2)
+ {
+ if (meth2 == null) return false;
+ int n = this.TemplateParameters == null ? 0 : this.TemplateParameters.Count;
+ int m = meth2.TemplateParameters == null ? 0 : meth2.TemplateParameters.Count;
+ return n == m;
+ }
+ public override string ToString()
+ {
+ return this.DeclaringType.GetFullUnmangledNameWithTypeParameters() + "." + this.Name;
+ }
+#if !MinimalReader
+ public bool GetIsCompilerGenerated()
+ {
+ InstanceInitializer ii = this as InstanceInitializer;
+ return this.HasCompilerGeneratedSignature || (ii != null && ii.IsCompilerGenerated);
+ }
+#endif
+#if FxCop
+ internal override void GetName(MemberFormat options, StringBuilder name)
+ {
+ base.GetName(options, name);
+ AppendTypeParameters(options, name);
+ AppendParametersAndReturnType(options, this.Parameters, '(', ')', this.ReturnType, name);
+ }
+ private void AppendTypeParameters(MemberFormat options, StringBuilder name)
+ {
+ if (options.ShowGenericMethodTypeParameterNames == false
+ || this.templateParameters == null
+ || this.templateParameters.Count == 0)
+ return;
+
+ name.Append('<');
+ TypeNodeList templateParameters = this.TemplateParameters;
+ for (int i = 0; i < templateParameters.Count; i++)
+ {
+ TypeNode templateParameter = templateParameters[i];
+ if (i != 0)
+ {
+ name.Append(',');
+ if (options.InsertSpacesBetweenMethodTypeParameters)
+ name.Append(' ');
+ }
+ name.Append(templateParameter.Name.Name);
+ }
+ name.Append('>');
+ }
+
+ internal static void AppendParametersAndReturnType(MemberFormat options, ParameterCollection parameters, char parametersPrefix, char parametersSuffix, TypeNode returnType, StringBuilder name)
+ {
+ AppendParameters(options.Parameters, parameters, parametersPrefix, parametersSuffix, name);
+ AppendReturnType(options.ReturnType, returnType, name);
+ }
+
+ internal static void AppendParameters(ParameterFormat options, ParameterCollection parameters, char prefix, char suffix, StringBuilder name)
+ {
+ if (parameters == null)
+ return;
+
+ if (options.TypeName == TypeNameFormat.None && options.ShowParameterNames == false)
+ return;
+
+ name.Append(prefix);
+ for (int i = 0; i < parameters.Count; ++i)
+ {
+ Parameter parameter = parameters[i];
+ if (i > 0)
+ {
+ name.Append(',');
+ if (options.InsertSpacesBetweenParameters)
+ name.Append(' ');
+ }
+ if (options.TypeName != TypeNameFormat.None)
+ {
+ parameter.Type.GetName(options, name);
+ if (options.ShowParameterNames) name.Append(' ');
+ }
+ if (options.ShowParameterNames)
+ name.Append(parameter.Name.Name);
+ }
+ name.Append(suffix);
+ }
+
+ internal static void AppendReturnType(TypeFormat options, TypeNode returnType, StringBuilder name)
+ {
+ if (options.TypeName == TypeNameFormat.None)
+ return;
+
+ name.Append(':');
+ returnType.GetName(options, name);
+ }
+#endif
+ }
+#if !MinimalReader
+ public class ProxyMethod : Method
+ {
+ public Method ProxyFor;
+ public ProxyMethod(TypeNode declaringType, AttributeList attributes, Identifier name, ParameterList parameters, TypeNode returnType, Block body)
+ : base(declaringType, attributes, name, parameters, returnType, body) { }
+ }
+#endif
+ public class InstanceInitializer : Method
+ {
+#if !MinimalReader
+ /// <summary>
+ /// True if this constructor calls a constructor declared in the same class, as opposed to the base class.
+ /// </summary>
+ public bool IsDeferringConstructor;
+ /// <summary>
+ /// When the source uses the C# compatibility mode, base calls cannot be put after non-null
+ /// field initialization, but must be put before the body. But the user can specify where
+ /// the base ctor call should be performed by using "base;" as a marker. During parsing
+ /// this flag is set so the right code transformations can be performed at code generation.
+ /// </summary>
+ public bool ContainsBaseMarkerBecauseOfNonNullFields;
+ public Block BaseOrDefferingCallBlock;
+ public bool IsCompilerGenerated = false;
+#endif
+ public InstanceInitializer()
+ : base()
+ {
+ this.NodeType = NodeType.InstanceInitializer;
+ this.CallingConvention = CallingConventionFlags.HasThis;
+ this.Flags = MethodFlags.SpecialName | MethodFlags.RTSpecialName;
+ this.Name = StandardIds.Ctor;
+ this.ReturnType = CoreSystemTypes.Void;
+ }
+ public InstanceInitializer(MethodBodyProvider provider, object handle)
+ : base(provider, handle)
+ {
+ this.NodeType = NodeType.InstanceInitializer;
+ }
+#if !MinimalReader
+ public InstanceInitializer(TypeNode declaringType, AttributeList attributes, ParameterList parameters, Block body)
+ : this(declaringType, attributes, parameters, body, CoreSystemTypes.Void)
+ {
+ }
+ public InstanceInitializer(TypeNode declaringType, AttributeList attributes, ParameterList parameters, Block body, TypeNode returnType)
+ : base(declaringType, attributes, StandardIds.Ctor, parameters, null, body)
+ {
+ this.NodeType = NodeType.InstanceInitializer;
+ this.CallingConvention = CallingConventionFlags.HasThis;
+ this.Flags = MethodFlags.SpecialName | MethodFlags.RTSpecialName;
+ this.Name = StandardIds.Ctor;
+ this.ReturnType = returnType;
+ }
+#endif
+#if !NoReflection
+ protected System.Reflection.ConstructorInfo constructorInfo;
+ public virtual System.Reflection.ConstructorInfo GetConstructorInfo()
+ {
+ if (this.constructorInfo == null)
+ {
+ if (this.DeclaringType == null) return null;
+ Type t = this.DeclaringType.GetRuntimeType();
+ if (t == null) return null;
+ ParameterList pars = this.Parameters;
+ int n = pars == null ? 0 : pars.Count;
+ Type[] types = new Type[n];
+ for (int i = 0; i < n; i++)
+ {
+ Parameter p = pars[i];
+ if (p == null || p.Type == null) return null;
+ Type pt = types[i] = p.Type.GetRuntimeType();
+ if (pt == null) return null;
+ }
+ System.Reflection.MemberInfo[] members = t.GetMember(this.Name.ToString(), System.Reflection.MemberTypes.Constructor,
+ BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+ foreach (System.Reflection.ConstructorInfo cons in members)
+ {
+ if (cons == null) continue;
+ System.Reflection.ParameterInfo[] parameters = cons.GetParameters();
+ if (parameters != null)
+ {
+ if (parameters.Length != n) continue;
+ for (int i = 0; i < n; i++)
+ {
+ System.Reflection.ParameterInfo par = parameters[i];
+ if (par == null || par.ParameterType != types[i]) goto tryNext;
+ }
+ }
+ return this.constructorInfo = cons;
+ tryNext: ;
+ }
+ }
+ return this.constructorInfo;
+ }
+#endif
+#if !NoReflection
+ public override System.Reflection.MethodInfo GetMethodInfo()
+ {
+ return null;
+ }
+ public virtual object Invoke(params object[] arguments)
+ {
+ System.Reflection.ConstructorInfo constr = this.GetConstructorInfo();
+ if (constr == null) return null;
+ return constr.Invoke(arguments);
+ }
+ public virtual Literal Invoke(params Literal[] arguments)
+ {
+ int n = arguments == null ? 0 : arguments.Length;
+ object[] args = n == 0 ? null : new object[n];
+ if (args != null && arguments != null)
+ for (int i = 0; i < n; i++)
+ {
+ Literal lit = arguments[i];
+ args[i] = lit == null ? null : lit.Value;
+ }
+ return new Literal(this.Invoke(args));
+ }
+#endif
+ //initializers never override a base class initializer
+ public override bool OverridesBaseClassMember
+ {
+ get { return false; }
+ set { }
+ }
+ public override Member OverriddenMember
+ {
+ get { return null; }
+ set { }
+ }
+ public override Method OverriddenMethod
+ {
+ get { return null; }
+ set { }
+ }
+ public override string ToString()
+ {
+ return this.DeclaringType.GetFullUnmangledNameWithTypeParameters() + "(" + this.Parameters + ")";
+ }
+#if !MinimalReader
+ public virtual MemberList GetAttributeConstructorNamedParameters()
+ {
+ TypeNode type = this.DeclaringType;
+ if (type == null || !type.IsAssignableTo(SystemTypes.Attribute) || type.Members == null)
+ return null;
+ MemberList memList = type.Members;
+ int n = memList.Count;
+ MemberList ml = new MemberList(memList.Count);
+ for (int i = 0; i < n; ++i)
+ {
+ Property p = memList[i] as Property;
+ if (p != null && p.IsPublic)
+ {
+ if (p.Setter != null && p.Getter != null)
+ ml.Add(p);
+ continue;
+ }
+ Field f = memList[i] as Field;
+ if (f != null && !f.IsInitOnly && f.IsPublic)
+ {
+ ml.Add(f);
+ }
+ }
+ return ml;
+ }
+#endif
+#if FxCop
+ internal override void GetName(MemberFormat options, StringBuilder name)
+ {
+ GetInitializerName(options, this.DeclaringType, this.Parameters, name, StandardIds.Ctor.Name);
+ }
+ internal static void GetInitializerName(MemberFormat options, TypeNode declaringType, ParameterCollection parameters, StringBuilder name, string methodName)
+ {
+ if (options.Type.TypeName != TypeNameFormat.None)
+ {
+ declaringType.GetName(options, name);
+ name.Append('.');
+ }
+ name.Append(methodName);
+ AppendParameters(options.Parameters, parameters, '(', ')', name);
+ }
+#endif
+ }
+ public class StaticInitializer : Method
+ {
+ public StaticInitializer()
+ : base()
+ {
+ this.NodeType = NodeType.StaticInitializer;
+ this.Flags = MethodFlags.SpecialName | MethodFlags.RTSpecialName | MethodFlags.Static | MethodFlags.HideBySig | MethodFlags.Private;
+ this.Name = StandardIds.CCtor;
+ this.ReturnType = CoreSystemTypes.Void;
+ }
+ public StaticInitializer(MethodBodyProvider provider, object handle)
+ : base(provider, handle)
+ {
+ this.NodeType = NodeType.StaticInitializer;
+ }
+#if !MinimalReader
+ public StaticInitializer(TypeNode declaringType, AttributeList attributes, Block body)
+ : base(declaringType, attributes, StandardIds.CCtor, null, null, body)
+ {
+ this.NodeType = NodeType.StaticInitializer;
+ this.Flags = MethodFlags.SpecialName | MethodFlags.RTSpecialName | MethodFlags.Static | MethodFlags.HideBySig | MethodFlags.Private;
+ this.Name = StandardIds.CCtor;
+ this.ReturnType = CoreSystemTypes.Void;
+ }
+ public StaticInitializer(TypeNode declaringType, AttributeList attributes, Block body, TypeNode voidTypeExpression)
+ : base(declaringType, attributes, StandardIds.CCtor, null, null, body)
+ {
+ this.NodeType = NodeType.StaticInitializer;
+ this.Flags = MethodFlags.SpecialName | MethodFlags.RTSpecialName | MethodFlags.Static | MethodFlags.HideBySig | MethodFlags.Private;
+ this.Name = StandardIds.CCtor;
+ this.ReturnType = voidTypeExpression;
+ }
+#endif
+#if !NoReflection
+ protected System.Reflection.ConstructorInfo constructorInfo;
+ public virtual System.Reflection.ConstructorInfo GetConstructorInfo()
+ {
+ if (this.constructorInfo == null)
+ {
+ if (this.DeclaringType == null) return null;
+ Type t = this.DeclaringType.GetRuntimeType();
+ if (t == null) return null;
+ ParameterList pars = this.Parameters;
+ int n = pars == null ? 0 : pars.Count;
+ Type[] types = new Type[n];
+ for (int i = 0; i < n; i++)
+ {
+ Parameter p = pars[i];
+ if (p == null || p.Type == null) return null;
+ Type pt = types[i] = p.Type.GetRuntimeType();
+ if (pt == null) return null;
+ }
+ System.Reflection.MemberInfo[] members = t.GetMember(this.Name.ToString(), System.Reflection.MemberTypes.Constructor,
+ BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
+ foreach (System.Reflection.ConstructorInfo cons in members)
+ {
+ if (cons == null) continue;
+ System.Reflection.ParameterInfo[] parameters = cons.GetParameters();
+ int numPars = parameters == null ? 0 : parameters.Length;
+ if (numPars != n) continue;
+ if (parameters != null)
+ for (int i = 0; i < n; i++)
+ {
+ System.Reflection.ParameterInfo par = parameters[i];
+ if (par == null || par.ParameterType != types[i]) goto tryNext;
+ }
+ return this.constructorInfo = cons;
+ tryNext: ;
+ }
+ }
+ return this.constructorInfo;
+ }
+ public override System.Reflection.MethodInfo GetMethodInfo()
+ {
+ return null;
+ }
+#endif
+ //initializers never override a base class initializer
+ public override bool OverridesBaseClassMember
+ {
+ get { return false; }
+ set { }
+ }
+ public override Member OverriddenMember
+ {
+ get { return null; }
+ set { }
+ }
+ public override Method OverriddenMethod
+ {
+ get { return null; }
+ set { }
+ }
+#if FxCop
+ internal override void GetName(MemberFormat options, StringBuilder name)
+ {
+ InstanceInitializer.GetInitializerName(options, this.DeclaringType, this.Parameters, name, StandardIds.CCtor.Name);
+ }
+#endif
+ }
+#if !MinimalReader
+ public class FieldInitializerBlock : Block
+ {
+ public TypeNode Type;
+ public bool IsStatic;
+ public FieldInitializerBlock()
+ : base()
+ {
+ this.NodeType = NodeType.FieldInitializerBlock;
+ }
+ public FieldInitializerBlock(TypeNode type, bool isStatic)
+ : base()
+ {
+ this.NodeType = NodeType.FieldInitializerBlock;
+ this.Type = type;
+ this.IsStatic = isStatic;
+ }
+ }
+#endif
+#if !MinimalReader
+ public class ParameterField : Field
+ {
+ protected Parameter parameter;
+ public ParameterField()
+ {
+ }
+ public ParameterField(TypeNode declaringType, AttributeList attributes, FieldFlags flags, Identifier name,
+ TypeNode Type, Literal defaultValue)
+ : base(declaringType, attributes, flags, name, Type, defaultValue)
+ {
+ }
+ public virtual Parameter Parameter
+ {
+ get
+ {
+ return this.parameter;
+ }
+ set
+ {
+ this.parameter = value;
+ }
+ }
+ }
+#endif
+ public class Field : Member
+ {
+#if !MinimalReader
+ /// <summary>Provides a value that is assigned to the field upon initialization.</summary>
+ public Expression Initializer;
+ public TypeNode TypeExpression;
+ public bool HasOutOfBandContract;
+ public InterfaceList ImplementedInterfaces;
+ public InterfaceList ImplementedInterfaceExpressions;
+ // if this is the backing field for some event, then ForEvent is that event
+ public Event ForEvent;
+ public bool IsModelfield = false; //set to true if this field serves as the representation of a modelfield in a class
+#endif
+ public Field()
+ : base(NodeType.Field)
+ {
+ }
+ public Field(Identifier name)
+ : base(NodeType.Field)
+ {
+ this.Name = name;
+ }
+ public Field(TypeNode declaringType, AttributeList attributes, FieldFlags flags, Identifier name,
+ TypeNode type, Literal defaultValue)
+ : base(declaringType, attributes, name, NodeType.Field)
+ {
+ this.defaultValue = defaultValue;
+ this.flags = flags;
+ this.type = type;
+ }
+ private Literal defaultValue;
+ /// <summary>The compile-time value to be substituted for references to this field if it is a literal.</summary>
+ public Literal DefaultValue
+ { //TODO: rename this to LiteralValue
+ get { return this.defaultValue; }
+ set { this.defaultValue = value; }
+ }
+ private FieldFlags flags;
+ public FieldFlags Flags
+ {
+ get { return this.flags; }
+ set { this.flags = value; }
+ }
+ private int offset;
+ public int Offset
+ {
+ get { return this.offset; }
+ set { this.offset = value; }
+ }
+ private bool isVolatile;
+ /// <summary>True if the field may not be cached. Used for sharing data between multiple threads.</summary>
+ public bool IsVolatile
+ {
+ get { return this.isVolatile; }
+ set { this.isVolatile = value; }
+ }
+ private TypeNode type;
+ /// <summary>The type of values that may be stored in the field.</summary>
+ public TypeNode Type
+ {
+ get { return this.type; }
+ set { this.type = value; }
+ }
+ private MarshallingInformation marshallingInformation;
+ public MarshallingInformation MarshallingInformation
+ {
+ get { return this.marshallingInformation; }
+ set { this.marshallingInformation = value; }
+ }
+ private byte[] initialData;
+ public byte[] InitialData
+ {
+ get { return this.initialData; }
+ set { this.initialData = value; }
+ }
+ internal PESection section;
+ public PESection Section
+ {
+ get { return this.section; }
+ set { this.section = value; }
+ }
+ protected string fullName;
+ public override string/*!*/ FullName
+ {
+ get
+ {
+ string result = this.fullName;
+ if (result == null)
+ this.fullName = result = this.DeclaringType.FullName + "." + (this.Name == null ? "" : this.Name.ToString());
+ return result;
+ }
+ }
+#if !NoXml
+ protected override Identifier GetDocumentationId()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("F:");
+ if (this.DeclaringType == null) return Identifier.Empty;
+ sb.Append(this.DeclaringType.FullName);
+ sb.Append(".");
+ if (this.Name == null) return Identifier.Empty;
+ sb.Append(this.Name.Name);
+ return Identifier.For(sb.ToString());
+ }
+#endif
+#if !NoReflection
+ public static Field GetField(System.Reflection.FieldInfo fieldInfo)
+ {
+ if (fieldInfo == null) return null;
+ TypeNode tn = TypeNode.GetTypeNode(fieldInfo.DeclaringType);
+ if (tn == null) return null;
+ return tn.GetField(Identifier.For(fieldInfo.Name));
+ }
+#endif
+#if !NoReflection
+ protected System.Reflection.FieldInfo fieldInfo;
+ public virtual System.Reflection.FieldInfo GetFieldInfo()
+ {
+ if (this.fieldInfo == null)
+ {
+ TypeNode tn = this.DeclaringType;
+ if (tn == null) return null;
+ Type t = tn.GetRuntimeType();
+ if (t == null) return null;
+ System.Reflection.BindingFlags flags = System.Reflection.BindingFlags.DeclaredOnly;
+ if (this.IsPublic) flags |= System.Reflection.BindingFlags.Public; else flags |= System.Reflection.BindingFlags.NonPublic;
+ if (this.IsStatic) flags |= System.Reflection.BindingFlags.Static; else flags |= System.Reflection.BindingFlags.Instance;
+ this.fieldInfo = t.GetField(this.Name.ToString(), flags);
+ }
+ return this.fieldInfo;
+ }
+#endif
+ /// <summary>True if all references to the field are replaced with a value that is determined at compile-time.</summary>
+ public virtual bool IsLiteral
+ {
+ get { return (this.Flags & FieldFlags.Literal) != 0; }
+ }
+ public override bool IsAssembly
+ {
+ get { return (this.Flags & FieldFlags.FieldAccessMask) == FieldFlags.Assembly; }
+ }
+ public override bool IsCompilerControlled
+ {
+ get { return (this.Flags & FieldFlags.FieldAccessMask) == FieldFlags.CompilerControlled; }
+ }
+ public override bool IsFamily
+ {
+ get { return (this.Flags & FieldFlags.FieldAccessMask) == FieldFlags.Family; }
+ }
+ public override bool IsFamilyAndAssembly
+ {
+ get { return (this.Flags & FieldFlags.FieldAccessMask) == FieldFlags.FamANDAssem; }
+ }
+ public override bool IsFamilyOrAssembly
+ {
+ get { return (this.Flags & FieldFlags.FieldAccessMask) == FieldFlags.FamORAssem; }
+ }
+ /// <summary>True if the field may only be assigned to inside the constructor.</summary>
+ public virtual bool IsInitOnly
+ {
+ get { return (this.Flags & FieldFlags.InitOnly) != 0; }
+ }
+ public override bool IsPrivate
+ {
+ get { return (this.Flags & FieldFlags.FieldAccessMask) == FieldFlags.Private; }
+ }
+ public override bool IsPublic
+ {
+ get { return (this.Flags & FieldFlags.FieldAccessMask) == FieldFlags.Public; }
+ }
+ public override bool IsSpecialName
+ {
+ get { return (this.Flags & FieldFlags.SpecialName) != 0; }
+ }
+ public override bool IsStatic
+ {
+ get { return (this.Flags & FieldFlags.Static) != 0; }
+ }
+ public override bool IsVisibleOutsideAssembly
+ {
+ get
+ {
+ if (this.DeclaringType != null && !this.DeclaringType.IsVisibleOutsideAssembly) return false;
+ switch (this.Flags & FieldFlags.FieldAccessMask)
+ {
+ case FieldFlags.Public:
+ return true;
+ case FieldFlags.Family:
+ case FieldFlags.FamORAssem:
+ return this.DeclaringType != null && !this.DeclaringType.IsSealed;
+ default:
+ return false;
+ }
+ }
+ }
+#if !NoReflection
+ public virtual object GetValue(object targetObject)
+ {
+ System.Reflection.FieldInfo fieldInfo = this.GetFieldInfo();
+ if (fieldInfo == null) return null;
+ return fieldInfo.GetValue(targetObject);
+ }
+ public virtual Literal GetValue(Literal/*!*/ targetObject)
+ {
+ return new Literal(this.GetValue(targetObject.Value));
+ }
+ public virtual void SetValue(object targetObject, object value)
+ {
+ System.Reflection.FieldInfo fieldInfo = this.GetFieldInfo();
+ if (fieldInfo == null) return;
+ fieldInfo.SetValue(targetObject, value);
+ }
+ public virtual void SetValue(Literal/*!*/ targetObject, Literal/*!*/ value)
+ {
+ this.SetValue(targetObject.Value, value.Value);
+ }
+#endif
+#if ExtendedRuntime
+ ReferenceFieldSemantics referenceSemantics;
+ public ReferenceFieldSemantics ReferenceSemantics{
+ get{
+ if (this.referenceSemantics == ReferenceFieldSemantics.NotComputed){
+ ReferenceFieldSemantics referenceKind;
+ TypeNode t = this.Type;
+ if (t == null) return this.referenceSemantics;
+ if (t is Struct){
+ TypeNodeList args;
+ bool b = t.IsAssignableToInstanceOf(SystemTypes.GenericIEnumerable, out args);
+ if ( b && args!= null && args.Count > 0 && args[0] != null && args[0].IsObjectReferenceType)
+ referenceKind = ReferenceFieldSemantics.EnumerableStructOfReferences;
+ else if (t.IsAssignableTo(SystemTypes.IEnumerable))
+ referenceKind = ReferenceFieldSemantics.EnumerableStructOfReferences;
+ else
+ referenceKind = ReferenceFieldSemantics.NonReference;
+ }else if (t != null && t.IsObjectReferenceType)
+ referenceKind = ReferenceFieldSemantics.Reference;
+ else
+ referenceKind = ReferenceFieldSemantics.NonReference;
+ if (referenceKind == ReferenceFieldSemantics.NonReference)
+ this.referenceSemantics = referenceKind | ReferenceFieldSemantics.None;
+ else{
+ if (this.GetAttribute(SystemTypes.LockProtectedAttribute) != null)
+ this.referenceSemantics = referenceKind | ReferenceFieldSemantics.LockProtected;
+ else if (this.GetAttribute(SystemTypes.ImmutableAttribute) != null)
+ this.referenceSemantics = referenceKind | ReferenceFieldSemantics.Immutable;
+ else if (this.GetAttribute(SystemTypes.RepAttribute) != null)
+ this.referenceSemantics = referenceKind | ReferenceFieldSemantics.Rep;
+ else if (this.GetAttribute(SystemTypes.PeerAttribute) != null)
+ this.referenceSemantics = referenceKind | ReferenceFieldSemantics.Peer;
+ else {
+ bool isRep = false;
+ bool isPeer = false;
+ AttributeNode attr = this.GetAttribute(SystemTypes.OwnedAttribute);
+ if (attr != null) {
+ ExpressionList exprs = attr.Expressions;
+ if (exprs != null && exprs.Count > 0) {
+ Expression arg = exprs[0];
+ Literal lit = arg as Literal;
+ if (lit != null) {
+ if (lit.Value is bool)
+ isRep = (bool)lit.Value;
+ else if (lit.Value is string) {
+ isRep = (string)lit.Value == "this";
+ isPeer = (string)lit.Value == "peer";
+ }
+ }
+ for (int n = attr.Expressions == null ? 0 : attr.Expressions.Count, i = 0; i < n; i++) {
+ Expression e = attr.Expressions[i];
+ AssignmentExpression ae = e as AssignmentExpression;
+ if (ae != null) {
+ AssignmentStatement s = ae.AssignmentStatement as AssignmentStatement;
+ if (s != null) {
+ Literal lit2 = s.Source as Literal;
+ if (lit2 != null && lit2.Value is bool)
+ isRep = (bool)lit2.Value;
+ else if (lit2 != null && lit2.Value is string) {
+ isRep = (string)lit2.Value == "this";
+ isPeer = (string)lit2.Value == "peer";
+
+ }
+
+ }
+ }
+ }
+ } else {
+ // this is the default case: [Owned] without any arguments
+ isRep = true;
+ }
+ }
+ ReferenceFieldSemantics r = ReferenceFieldSemantics.None;
+ if (isRep) r = ReferenceFieldSemantics.Rep;
+ if (isPeer) r = ReferenceFieldSemantics.Peer;
+ this.referenceSemantics = referenceKind | r;
+ }
+ }
+ }
+ return this.referenceSemantics;
+ }
+ set {
+ this.referenceSemantics = value;
+ }
+ }
+ public bool IsOwned{
+ get{
+ return this.IsRep || this.IsPeer;
+ }
+ }
+ public bool IsOnce
+ {
+ get {
+ return this.GetAttribute(SystemTypes.OnceAttribute) != null;
+ }
+ }
+
+ public bool IsRep{
+ get {
+ return this.ReferenceSemantics == (ReferenceFieldSemantics.Rep | ReferenceFieldSemantics.Reference);
+ }
+ }
+ public bool IsPeer {
+ get {
+ return this.ReferenceSemantics == (ReferenceFieldSemantics.Peer | ReferenceFieldSemantics.Reference);
+ }
+ }
+ public bool IsLockProtected {
+ get{
+ return this.ReferenceSemantics == (ReferenceFieldSemantics.LockProtected | ReferenceFieldSemantics.Reference);
+ }
+ }
+ public bool IsStrictReadonly {
+ get {
+ return this.GetAttribute(ExtendedRuntimeTypes.StrictReadonlyAttribute) != null;
+ }
+ }
+#endif
+ public override string ToString()
+ {
+ return this.DeclaringType.GetFullUnmangledNameWithTypeParameters() + "." + this.Name;
+ }
+#if FxCop
+ internal override void GetName(MemberFormat options, StringBuilder name)
+ {
+ base.GetName(options, name);
+ Method.AppendReturnType(options.ReturnType, this.Type, name);
+ }
+#endif
+ }
+#if ExtendedRuntime
+ /// <summary>
+ /// The behavior of a field in the Spec# object invariants/ownership/concurrency methodology.
+ /// </summary>
+ public enum ReferenceFieldSemantics{
+ NotComputed,
+ None,
+ Rep,
+ LockProtected,
+ Immutable,
+ Peer,
+ SemanticsMask = 0xff,
+ Reference = 0x100,
+ EnumerableStructOfReferences = 0x200,
+ NonReference = 0x300,
+ ReferenceMask = 0xff00,
+ }
+#endif
+#if FxCop
+ public class PropertyNode : Member{
+#else
+ public class Property : Member
+ {
+#endif
+#if !MinimalReader
+ /// <summary>
+ /// The list of types (just one in C#) that contain abstract or virtual properties that are explicity implemented or overridden by this property.
+ /// </summary>
+ public TypeNodeList ImplementedTypes;
+ public TypeNodeList ImplementedTypeExpressions;
+ public bool IsModelfield = false; //set to true if this property serves as the representation of a modelfield in an interface
+#endif
+#if FxCop
+ public PropertyNode()
+#else
+ public Property()
+#endif
+ : base(NodeType.Property)
+ {
+ }
+#if !MinimalReader
+ public Property(TypeNode declaringType, AttributeList attributes, PropertyFlags flags, Identifier name,
+ Method getter, Method setter)
+ : base(declaringType, attributes, name, NodeType.Property)
+ {
+ this.flags = flags;
+ this.getter = getter;
+ this.setter = setter;
+ if (getter != null) getter.DeclaringMember = this;
+ if (setter != null) setter.DeclaringMember = this;
+ }
+#endif
+ private PropertyFlags flags;
+ public PropertyFlags Flags
+ {
+ get { return this.flags; }
+ set { this.flags = value; }
+ }
+ private Method getter;
+ /// <summary>The method that is called to get the value of this property. Corresponds to the get clause in C#.</summary>
+ public Method Getter
+ {
+ get { return this.getter; }
+ set { this.getter = value; }
+ }
+ private Method setter;
+ /// <summary>The method that is called to set the value of this property. Corresponds to the set clause in C#.</summary>
+ public Method Setter
+ {
+ get { return this.setter; }
+ set { this.setter = value; }
+ }
+ private MethodList otherMethods;
+ /// <summary>Other methods associated with the property. No equivalent in C#.</summary>
+ public MethodList OtherMethods
+ {
+ get { return this.otherMethods; }
+ set { this.otherMethods = value; }
+ }
+ protected string fullName;
+ public override string/*!*/ FullName
+ {
+ get
+ {
+ if (this.fullName != null) return this.fullName;
+ StringBuilder sb = new StringBuilder();
+ sb.Append(this.DeclaringType.FullName);
+ sb.Append('.');
+ if (this.Name != null)
+ sb.Append(this.Name.ToString());
+ ParameterList parameters = this.Parameters;
+ for (int i = 0, n = parameters == null ? 0 : parameters.Count; i < n; i++)
+ {
+ Parameter par = parameters[i];
+ if (par == null || par.Type == null) continue;
+ if (i == 0)
+ sb.Append('(');
+ else
+ sb.Append(',');
+ sb.Append(par.Type.FullName);
+ if (i == n - 1)
+ sb.Append(')');
+ }
+ return this.fullName = sb.ToString();
+ }
+ }
+#if !MinimalReader
+ public virtual Method GetBaseGetter()
+ {
+ TypeNode t = this.DeclaringType;
+ if (t == null) return null;
+ while (t.BaseType != null)
+ {
+ t = t.BaseType;
+ MemberList mems = t.GetMembersNamed(this.Name);
+ for (int i = 0, n = mems == null ? 0 : mems.Count; i < n; i++)
+ {
+ Property bprop = mems[i] as Property;
+ if (bprop == null) continue;
+ if (!bprop.ParametersMatch(this.Parameters)) continue;
+ if (bprop.Getter != null) return bprop.Getter;
+ }
+ }
+ return null;
+ }
+ public virtual Method GetBaseSetter()
+ {
+ TypeNode t = this.DeclaringType;
+ if (t == null) return null;
+ while (t.BaseType != null)
+ {
+ t = t.BaseType;
+ MemberList mems = t.GetMembersNamed(this.Name);
+ for (int i = 0, n = mems == null ? 0 : mems.Count; i < n; i++)
+ {
+ Property bprop = mems[i] as Property;
+ if (bprop == null) continue;
+ if (!bprop.ParametersMatch(this.Parameters)) continue;
+ if (bprop.Setter != null) return bprop.Setter;
+ }
+ }
+ return null;
+ }
+#endif
+#if !NoXml
+ protected override Identifier GetDocumentationId()
+ {
+ StringBuilder sb = new StringBuilder(this.DeclaringType.DocumentationId.ToString());
+ sb[0] = 'P';
+ sb.Append('.');
+ if (this.Name != null)
+ sb.Append(this.Name.ToString());
+ ParameterList parameters = this.Parameters;
+ for (int i = 0, n = parameters == null ? 0 : parameters.Count; i < n; i++)
+ {
+ Parameter par = parameters[i];
+ if (par == null || par.Type == null) continue;
+ if (i == 0)
+ sb.Append('(');
+ else
+ sb.Append(',');
+ par.Type.AppendDocumentIdMangledName(sb, null, this.DeclaringType.TemplateParameters);
+ if (i == n - 1)
+ sb.Append(')');
+ }
+ return Identifier.For(sb.ToString());
+ }
+#endif
+#if !NoReflection
+ public static Property GetProperty(System.Reflection.PropertyInfo propertyInfo)
+ {
+ if (propertyInfo == null) return null;
+ TypeNode tn = TypeNode.GetTypeNode(propertyInfo.DeclaringType);
+ if (tn == null) return null;
+ System.Reflection.ParameterInfo[] paramInfos = propertyInfo.GetIndexParameters();
+ int n = paramInfos == null ? 0 : paramInfos.Length;
+ TypeNode[] parameterTypes = new TypeNode[n];
+ if (paramInfos != null)
+ for (int i = 0; i < n; i++)
+ {
+ System.Reflection.ParameterInfo param = paramInfos[i];
+ if (param == null) return null;
+ parameterTypes[i] = TypeNode.GetTypeNode(param.ParameterType);
+ }
+ return tn.GetProperty(Identifier.For(propertyInfo.Name), parameterTypes);
+ }
+#endif
+
+#if !NoReflection
+ protected System.Reflection.PropertyInfo propertyInfo;
+ public virtual System.Reflection.PropertyInfo GetPropertyInfo()
+ {
+ if (this.propertyInfo == null)
+ {
+ if (this.DeclaringType == null) return null;
+ Type t = this.DeclaringType.GetRuntimeType();
+ if (t == null) return null;
+ if (this.Type == null) return null;
+ Type retType = this.Type.GetRuntimeType();
+ if (retType == null) return null;
+ ParameterList pars = this.Parameters;
+ int n = pars == null ? 0 : pars.Count;
+ Type[] types = new Type[n];
+ for (int i = 0; i < n; i++)
+ {
+ Parameter p = pars[i];
+ if (p == null || p.Type == null) return null;
+ Type pt = types[i] = p.Type.GetRuntimeType();
+ if (pt == null) return null;
+ }
+ System.Reflection.MemberInfo[] members =
+ t.GetMember(this.Name.ToString(), System.Reflection.MemberTypes.Property,
+ BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
+ foreach (System.Reflection.PropertyInfo prop in members)
+ {
+ if (prop == null || prop.PropertyType != retType) continue;
+ System.Reflection.ParameterInfo[] parameters = prop.GetIndexParameters();
+ if (parameters == null || parameters.Length != n) continue;
+ for (int i = 0; i < n; i++)
+ {
+ System.Reflection.ParameterInfo parInfo = parameters[i];
+ if (parInfo == null || parInfo.ParameterType != types[i]) goto tryNext;
+ }
+ return this.propertyInfo = prop;
+ tryNext: ;
+ }
+ }
+ return this.propertyInfo;
+ }
+ public virtual object GetValue(object targetObject, params object[] indices)
+ {
+ System.Reflection.PropertyInfo propInfo = this.GetPropertyInfo();
+ if (propInfo == null) throw new InvalidOperationException();
+ return propInfo.GetValue(targetObject, indices);
+ }
+ public virtual Literal GetValue(Literal/*!*/ targetObject, params Literal[] indices)
+ {
+ int n = indices == null ? 0 : indices.Length;
+ object[] inds = n == 0 ? null : new object[n];
+ if (inds != null && indices != null)
+ for (int i = 0; i < n; i++)
+ {
+ Literal lit = indices[i];
+ inds[i] = lit == null ? null : lit.Value;
+ }
+ return new Literal(this.GetValue(targetObject.Value, inds));
+ }
+ public virtual void SetValue(object targetObject, object value, params object[] indices)
+ {
+ System.Reflection.PropertyInfo propInfo = this.GetPropertyInfo();
+ if (propInfo == null) throw new InvalidOperationException();
+ propInfo.SetValue(targetObject, value, indices);
+ }
+ public virtual void SetValue(Literal/*!*/ targetObject, Literal/*!*/ value, params Literal[] indices)
+ {
+ int n = indices == null ? 0 : indices.Length;
+ object[] inds = n == 0 ? null : new object[n];
+ if (inds != null && indices != null)
+ for (int i = 0; i < n; i++)
+ {
+ Literal lit = indices[i];
+ inds[i] = lit == null ? null : lit.Value;
+ }
+ System.Reflection.PropertyInfo propInfo = this.GetPropertyInfo();
+ if (propInfo == null) throw new InvalidOperationException();
+ propInfo.SetValue(targetObject.Value, value.Value, inds);
+ }
+#endif
+#if !NoXml
+ public override string HelpText
+ {
+ get
+ {
+ if (this.helpText != null)
+ return this.helpText;
+ StringBuilder sb = new StringBuilder(base.HelpText);
+ // if there is already some help text, start the contract on a new line
+ bool startWithNewLine = (sb.Length != 0);
+ if (this.Getter != null && this.Getter.HelpText != null && this.Getter.HelpText.Length > 0)
+ {
+ if (startWithNewLine)
+ {
+ sb.Append("\n");
+ startWithNewLine = false;
+ }
+ sb.Append("get\n");
+ int i = sb.Length;
+ sb.Append(this.Getter.HelpText);
+ if (sb.Length > i)
+ startWithNewLine = true;
+ }
+ if (this.Setter != null && this.Setter.HelpText != null && this.Setter.HelpText.Length > 0)
+ {
+ if (startWithNewLine)
+ {
+ sb.Append("\n");
+ startWithNewLine = false;
+ }
+ sb.Append("set\n");
+ sb.Append(this.Setter.HelpText);
+ }
+ return this.helpText = sb.ToString();
+ }
+ set
+ {
+ base.HelpText = value;
+ }
+ }
+#endif
+ public override bool IsAssembly
+ {
+ get { return Method.GetVisibilityUnion(this.Getter, this.Setter) == MethodFlags.Assembly; }
+ }
+ public override bool IsCompilerControlled
+ {
+ get { return Method.GetVisibilityUnion(this.Getter, this.Setter) == MethodFlags.CompilerControlled; }
+ }
+ public override bool IsFamily
+ {
+ get { return Method.GetVisibilityUnion(this.Getter, this.Setter) == MethodFlags.Family; }
+ }
+ public override bool IsFamilyAndAssembly
+ {
+ get { return Method.GetVisibilityUnion(this.Getter, this.Setter) == MethodFlags.FamANDAssem; }
+ }
+ public override bool IsFamilyOrAssembly
+ {
+ get { return Method.GetVisibilityUnion(this.Getter, this.Setter) == MethodFlags.FamORAssem; }
+ }
+ public bool IsFinal
+ {
+ get { return (this.Getter == null || this.Getter.IsFinal) && (this.Setter == null || this.Setter.IsFinal); }
+ }
+ public override bool IsPrivate
+ {
+ get { return Method.GetVisibilityUnion(this.Getter, this.Setter) == MethodFlags.Private; }
+ }
+ public override bool IsPublic
+ {
+ get { return Method.GetVisibilityUnion(this.Getter, this.Setter) == MethodFlags.Public; }
+ }
+ public override bool IsSpecialName
+ {
+ get { return (this.Flags & PropertyFlags.SpecialName) != 0; }
+ }
+ public override bool IsStatic
+ {
+ get { return (this.Getter == null || this.Getter.IsStatic) && (this.Setter == null || this.Setter.IsStatic); }
+ }
+ /// <summary>
+ /// True if this property can in principle be overridden by a property in a derived class.
+ /// </summary>
+ public bool IsVirtual
+ {
+ get { return (this.Getter == null || this.Getter.IsVirtual) && (this.Setter == null || this.Setter.IsVirtual); }
+ }
+ public override bool IsVisibleOutsideAssembly
+ {
+ get { return (this.Getter != null && this.Getter.IsVisibleOutsideAssembly) || (this.Setter != null && this.Setter.IsVisibleOutsideAssembly); }
+ }
+ public static readonly Property NotSpecified = new Property();
+ public override Member HiddenMember
+ {
+ get
+ {
+ return this.HiddenProperty;
+ }
+ set
+ {
+ this.HiddenProperty = (Property)value;
+ }
+ }
+ protected Property hiddenProperty;
+ public virtual Property HiddenProperty
+ {
+ get
+ {
+ if (this.hiddenMember == Property.NotSpecified) return null;
+ Property hiddenProperty = this.hiddenMember as Property;
+ if (hiddenProperty != null) return hiddenProperty;
+
+ Method hiddenGetter = this.Getter == null ? null : this.Getter.HiddenMethod;
+ Method hiddenSetter = this.Setter == null ? null : this.Setter.HiddenMethod;
+ Property hiddenGetterProperty = hiddenGetter == null ? null : hiddenGetter.DeclaringMember as Property;
+ Property hiddenSetterProperty = hiddenSetter == null ? null : hiddenSetter.DeclaringMember as Property;
+ hiddenProperty = hiddenGetterProperty;
+ if (hiddenSetterProperty != null)
+ {
+ if (hiddenProperty == null ||
+ (hiddenSetterProperty.DeclaringType != null && hiddenSetterProperty.DeclaringType.IsDerivedFrom(hiddenProperty.DeclaringType)))
+ hiddenProperty = hiddenSetterProperty;
+ }
+ this.hiddenMember = hiddenProperty;
+ return hiddenProperty;
+ }
+ set
+ {
+ this.hiddenMember = value;
+ }
+ }
+ public override Member OverriddenMember
+ {
+ get
+ {
+ return this.OverriddenProperty;
+ }
+ set
+ {
+ this.OverriddenProperty = (Property)value;
+ }
+ }
+ protected Property overriddenProperty;
+ public virtual Property OverriddenProperty
+ {
+ get
+ {
+ if (this.overriddenMember == Property.NotSpecified) return null;
+ Property overriddenProperty = this.overriddenMember as Property;
+ if (overriddenProperty != null) return overriddenProperty;
+
+ Method overriddenGetter = this.Getter == null ? null : this.Getter.OverriddenMethod;
+ Method overriddenSetter = this.Setter == null ? null : this.Setter.OverriddenMethod;
+ Property overriddenGetterProperty = overriddenGetter == null ? null : overriddenGetter.DeclaringMember as Property;
+ Property overriddenSetterProperty = overriddenSetter == null ? null : overriddenSetter.DeclaringMember as Property;
+ overriddenProperty = overriddenGetterProperty;
+ if (overriddenSetterProperty != null)
+ {
+ if (overriddenProperty == null ||
+ (overriddenSetterProperty.DeclaringType != null && overriddenSetterProperty.DeclaringType.IsDerivedFrom(overriddenProperty.DeclaringType)))
+ overriddenProperty = overriddenSetterProperty;
+ }
+ this.overriddenMember = overriddenProperty;
+ return overriddenProperty;
+ }
+ set
+ {
+ this.overriddenMember = value;
+ }
+ }
+ private ParameterList parameters;
+ /// <summary>
+ /// The parameters of this property if it is an indexer.
+ /// </summary>
+ public ParameterList Parameters
+ {
+ get
+ {
+ if (this.parameters != null) return this.parameters;
+ if (this.Getter != null) return this.parameters = this.Getter.Parameters;
+ ParameterList setterPars = this.Setter == null ? null : this.Setter.Parameters;
+ int n = setterPars == null ? 0 : setterPars.Count - 1;
+ ParameterList propPars = this.parameters = new ParameterList(n);
+ if (setterPars != null)
+ for (int i = 0; i < n; i++) propPars.Add(setterPars[i]);
+ return propPars;
+ }
+ set
+ {
+ this.parameters = value;
+ }
+ }
+ public virtual bool ParametersMatch(ParameterList parameters)
+ {
+ ParameterList pars = this.Parameters;
+ int n = pars == null ? 0 : pars.Count;
+ int m = parameters == null ? 0 : parameters.Count;
+ if (n != m) return false;
+ if (parameters == null) return true;
+ for (int i = 0; i < n; i++)
+ {
+ Parameter par1 = pars[i];
+ Parameter par2 = parameters[i];
+ if (par1.Type != par2.Type) return false;
+ }
+ return true;
+ }
+ public virtual bool ParametersMatchStructurally(ParameterList parameters)
+ {
+ ParameterList pars = this.Parameters;
+ int n = pars == null ? 0 : pars.Count;
+ int m = parameters == null ? 0 : parameters.Count;
+ if (n != m) return false;
+ if (parameters == null) return true;
+ for (int i = 0; i < n; i++)
+ {
+ Parameter par1 = pars[i];
+ Parameter par2 = parameters[i];
+ if (par1 == null || par2 == null) return false;
+ if (par1.Type == null || par2.Type == null) return false;
+ if (par1.Type != par2.Type && !par1.Type.IsStructurallyEquivalentTo(par2.Type)) return false;
+ }
+ return true;
+ }
+ public virtual bool ParameterTypesMatch(TypeNodeList argumentTypes)
+ {
+ ParameterList pars = this.Parameters;
+ int n = pars == null ? 0 : pars.Count;
+ int m = argumentTypes == null ? 0 : argumentTypes.Count;
+ if (n != m) return false;
+ if (argumentTypes == null) return true;
+ for (int i = 0; i < n; i++)
+ {
+ Parameter par = this.Parameters[i];
+ if (par == null) return false;
+ TypeNode argType = argumentTypes[i];
+ if (par.Type != argType) return false;
+ }
+ return true;
+ }
+ protected TypeNode type;
+ /// <summary>
+ /// The type of value that this property holds.
+ /// </summary>
+ public virtual TypeNode Type
+ {
+ get
+ {
+ if (this.type != null) return this.type;
+ if (this.Getter != null) return this.type = this.Getter.ReturnType;
+ if (this.Setter != null && this.Setter.Parameters != null)
+ return this.type = this.Setter.Parameters[this.Setter.Parameters.Count - 1].Type;
+ return CoreSystemTypes.Object;
+ }
+ set
+ {
+ this.type = value;
+ }
+ }
+#if !MinimalReader
+ public TypeNode TypeExpression;
+#endif
+ public override string ToString()
+ {
+ return this.DeclaringType.GetFullUnmangledNameWithTypeParameters() + "." + this.Name;
+ }
+#if FxCop
+ internal override void GetName(MemberFormat options, StringBuilder name)
+ {
+ base.GetName(options, name);
+ ParameterCollection parameters = this.parameters.Count > 0 ? this.parameters : null;
+ // AppendParametersAndReturnType will not emit the paramters
+ // prefix and suffix if a null ParameterCollection is provided to it.
+ // This prevents a parameterless property from being rendered as MyProperty[]
+ Method.AppendParametersAndReturnType(options, parameters, '[', ']', this.Type, name);
+ }
+#endif
+ }
+ public class Variable : Expression
+ {
+ private Identifier name;
+#if !MinimalReader
+ public TypeNode TypeExpression;
+#endif
+ public Variable(NodeType type)
+ : base(type)
+ {
+ }
+ /// <summary>The name of a stack location. For example the name of a local variable or the name of a method parameter.</summary>
+ public Identifier Name
+ {
+ get { return this.name; }
+ set { this.name = value; }
+ }
+ }
+ public class Parameter : Variable
+ {
+ private AttributeList attributes;
+ /// <summary>The (C# custom) attributes of this parameter.</summary>
+ public AttributeList Attributes
+ {
+ get
+ {
+ if (this.attributes != null) return this.attributes;
+ return this.attributes = new AttributeList();
+ }
+ set { this.attributes = value; }
+ }
+ private Expression defaultValue;
+ /// <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>
+ public Expression DefaultValue
+ {
+ get { return this.defaultValue; }
+ set { this.defaultValue = value; }
+ }
+ private ParameterFlags flags;
+ public ParameterFlags Flags
+ {
+ get { return this.flags; }
+ set { this.flags = value; }
+ }
+ private MarshallingInformation marshallingInformation;
+ public MarshallingInformation MarshallingInformation
+ {
+ get { return this.marshallingInformation; }
+ set { this.marshallingInformation = value; }
+ }
+ private Method declaringMethod;
+ public Method DeclaringMethod
+ {
+ get { return this.declaringMethod; }
+ set { this.declaringMethod = value; }
+ }
+ private int parameterListIndex;
+ /// <summary>
+ /// Zero based index into a parameter list containing this parameter.
+ /// </summary>
+ public int ParameterListIndex
+ {
+ get { return this.parameterListIndex; }
+ set { this.parameterListIndex = value; }
+ }
+ private int argumentListIndex;
+ /// <summary>
+ /// Zero based index into the list of arguments on the evaluation stack.
+ /// Instance methods have the this object as parameter zero, which means that the first parameter will have value 1, not 0.
+ /// </summary>
+ public int ArgumentListIndex
+ {
+ get { return this.argumentListIndex; }
+ set { this.argumentListIndex = value; }
+ }
+ public Parameter()
+ : base(NodeType.Parameter)
+ {
+ }
+ public Parameter(Identifier name, TypeNode type)
+ : base(NodeType.Parameter)
+ {
+ this.Name = name;
+ this.Type = type;
+ }
+#if !MinimalReader
+ public Parameter(AttributeList attributes, ParameterFlags flags, Identifier name, TypeNode type,
+ Literal defaultValue, MarshallingInformation marshallingInformation)
+ : base(NodeType.Parameter)
+ {
+ this.attributes = attributes;
+ this.defaultValue = defaultValue;
+ this.flags = flags;
+ this.marshallingInformation = marshallingInformation;
+ this.Name = name;
+ this.Type = type;
+ }
+#endif
+ /// <summary>
+ /// True if the corresponding argument value is used by the callee. (This need not be the case for a parameter marked as IsOut.)
+ /// </summary>
+ public virtual bool IsIn
+ {
+ get
+ {
+ return (this.Flags & ParameterFlags.In) != 0;
+ }
+ set
+ {
+ if (value)
+ this.Flags |= ParameterFlags.In;
+ else
+ this.Flags &= ~ParameterFlags.In;
+ }
+ }
+ /// <summary>
+ /// True if the caller can omit providing an argument for this parameter.
+ /// </summary>
+ public virtual bool IsOptional
+ {
+ get
+ {
+ return (this.Flags & ParameterFlags.Optional) != 0;
+ }
+ set
+ {
+ if (value)
+ this.Flags |= ParameterFlags.Optional;
+ else
+ this.Flags &= ~ParameterFlags.Optional;
+ }
+ }
+ /// <summary>
+ /// True if the corresponding argument must be a left hand expression and will be updated when the call returns.
+ /// </summary>
+ public virtual bool IsOut
+ {
+ get
+ {
+ return (this.Flags & ParameterFlags.Out) != 0;
+ }
+ set
+ {
+ if (value)
+ this.Flags |= ParameterFlags.Out;
+ else
+ this.Flags &= ~ParameterFlags.Out;
+ }
+ }
+#if !MinimalReader
+ protected TypeNode paramArrayElementType = null;
+ /// <summary>
+ /// If the parameter is a param array, this returns the element type of the array. If not, it returns null.
+ /// </summary>
+ public virtual TypeNode GetParamArrayElementType()
+ {
+ TypeNode result = this.paramArrayElementType;
+ if (result == null)
+ {
+ AttributeNode attr = this.GetParamArrayAttribute();
+ if (attr != null)
+ {
+ TypeNode t = TypeNode.StripModifiers(this.Type);
+ Reference r = t as Reference;
+ if (r != null) t = r.ElementType;
+ ArrayType arr = t as ArrayType;
+ if (arr != null && arr.Rank == 1)
+ return this.paramArrayElementType = arr.ElementType;
+ }
+ this.paramArrayElementType = result = Class.DoesNotExist;
+ }
+ if (result == Class.DoesNotExist) return null;
+ return result;
+ }
+ protected AttributeNode paramArrayAttribute = null;
+ public virtual AttributeNode GetParamArrayAttribute()
+ {
+ AttributeNode result = this.paramArrayAttribute;
+ if (result == null)
+ {
+ AttributeList attributes = this.Attributes;
+ for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++)
+ {
+ AttributeNode attr = attributes[i];
+ if (attr == null) continue;
+ TypeNode attrType = null;
+ MemberBinding mb = attr.Constructor as MemberBinding;
+ if (mb != null)
+ attrType = mb.BoundMember.DeclaringType;
+ else
+ {
+ Literal lit = attr.Constructor as Literal;
+ if (lit == null) continue;
+ attrType = lit.Value as TypeNode;
+ }
+ if (attrType == SystemTypes.ParamArrayAttribute)
+ return this.paramArrayAttribute = attr;
+ }
+ result = this.paramArrayAttribute = AttributeNode.DoesNotExist;
+ }
+ if (result == AttributeNode.DoesNotExist) return null;
+ return result;
+ }
+ public override bool Equals(object obj)
+ {
+ ParameterBinding binding = obj as ParameterBinding;
+ return obj == this || binding != null && binding.BoundParameter == this;
+ }
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+ /// <summary>
+ /// Gets the first attribute of the given type in the attribute list of this parameter. Returns null if none found.
+ /// This should not be called until the AST containing this member has been processed to replace symbolic references
+ /// to members with references to the actual members.
+ /// </summary>
+ public virtual AttributeNode GetAttribute(TypeNode attributeType)
+ {
+ if (attributeType == null) return null;
+ AttributeList attributes = this.Attributes;
+ for (int i = 0, n = attributes == null ? 0 : attributes.Count; i < n; i++)
+ {
+ AttributeNode attr = attributes[i];
+ if (attr == null) continue;
+ MemberBinding mb = attr.Constructor as MemberBinding;
+ if (mb != null)
+ {
+ if (mb.BoundMember == null) continue;
+ if (mb.BoundMember.DeclaringType != attributeType) continue;
+ return attr;
+ }
+ Literal lit = attr.Constructor as Literal;
+ if (lit == null) continue;
+ if ((lit.Value as TypeNode) != attributeType) continue;
+ return attr;
+ }
+ return null;
+ }
+#endif
+#if ExtendedRuntime
+ public virtual bool IsUniversallyDelayed {
+ get {
+ // Special handling of delegate constructors. Their first argument is delayed.
+ if (this.DeclaringMethod != null && this.DeclaringMethod.DeclaringType is DelegateNode) {
+ if (this.DeclaringMethod.Parameters[0] == this) { // first parameter (not including this)
+ return true;
+ }
+ }
+ return (this.GetAttribute(ExtendedRuntimeTypes.DelayedAttribute) != null);
+ }
+ }
+#endif
+ public override string ToString()
+ {
+ if (this.Name == null) return "";
+ if (this.Type == null) return this.Name.ToString();
+ return this.Type.ToString() + " " + this.Name.ToString();
+ }
+ }
+#if !MinimalReader
+ public class ParameterBinding : Parameter, IUniqueKey
+ {
+ public Parameter/*!*/ BoundParameter;
+
+ public ParameterBinding(Parameter/*!*/ boundParameter, SourceContext sctx)
+ {
+ if (boundParameter == null) throw new ArgumentNullException("boundParameter");
+ this.BoundParameter = boundParameter;
+ this.SourceContext = sctx;
+ this.Type = boundParameter.Type;
+ this.Name = boundParameter.Name;
+ this.TypeExpression = boundParameter.TypeExpression;
+ this.Attributes = boundParameter.Attributes;
+ this.DefaultValue = boundParameter.DefaultValue;
+ this.Flags = boundParameter.Flags;
+ this.MarshallingInformation = boundParameter.MarshallingInformation;
+ this.DeclaringMethod = boundParameter.DeclaringMethod;
+ this.ParameterListIndex = boundParameter.ParameterListIndex;
+ this.ArgumentListIndex = boundParameter.ArgumentListIndex;
+ //^ base();
+ }
+ public override int GetHashCode()
+ {
+ return this.BoundParameter.GetHashCode();
+ }
+ public override bool Equals(object obj)
+ {
+ ParameterBinding pb = obj as ParameterBinding;
+ if (pb != null)
+ return this.BoundParameter.Equals(pb.BoundParameter);
+ else
+ return this.BoundParameter.Equals(obj);
+ }
+ int IUniqueKey.UniqueId
+ {
+ get { return this.BoundParameter.UniqueKey; }
+ }
+ }
+#endif
+ public class Local : Variable
+ {
+#if !MinimalReader
+ public Block DeclaringBlock;
+ public bool InitOnly;
+ public int Index;
+#endif
+ public Local()
+ : base(NodeType.Local)
+ {
+ }
+ public Local(TypeNode type)
+ : base(NodeType.Local)
+ {
+ this.Name = Identifier.Empty;
+ if (type == null) type = CoreSystemTypes.Object;
+ this.Type = type;
+ }
+ public Local(Identifier name, TypeNode type)
+ : this(type)
+ {
+ this.Name = name;
+ }
+#if !MinimalReader
+ public Local(TypeNode type, SourceContext context)
+ : this(Identifier.Empty, type, null)
+ {
+ this.SourceContext = context;
+ }
+ public Local(Identifier name, TypeNode type, SourceContext context)
+ : this(name, type, null)
+ {
+ this.SourceContext = context;
+ }
+ public Local(Identifier name, TypeNode type, Block declaringBlock)
+ : base(NodeType.Local)
+ {
+ this.DeclaringBlock = declaringBlock;
+ this.Name = name;
+ if (type == null) type = CoreSystemTypes.Object;
+ this.Type = type;
+ }
+#endif
+ private bool pinned;
+ public bool Pinned
+ {
+ get { return this.pinned; }
+ set { this.pinned = value; }
+ }
+#if !MinimalReader
+ public override bool Equals(object obj)
+ {
+ LocalBinding binding = obj as LocalBinding;
+ return obj == this || binding != null && binding.BoundLocal == this;
+ }
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+ public override string ToString()
+ {
+ if (this.Name == null) return "No name";
+ return this.Name.ToString();
+ }
+#endif
+
+ }
+#if !MinimalReader
+ public class LocalBinding : Local, IUniqueKey
+ {
+ public Local/*!*/ BoundLocal;
+
+ public LocalBinding(Local/*!*/ boundLocal, SourceContext sctx)
+ {
+ if (boundLocal == null) throw new ArgumentNullException("boundLocal");
+ this.BoundLocal = boundLocal;
+ //^ base();
+ this.SourceContext = sctx;
+ this.Type = boundLocal.Type;
+ this.Name = boundLocal.Name;
+ this.TypeExpression = boundLocal.TypeExpression;
+ this.DeclaringBlock = boundLocal.DeclaringBlock;
+ this.Pinned = boundLocal.Pinned;
+ this.InitOnly = boundLocal.InitOnly;
+ this.Index = boundLocal.Index;
+ }
+ public override int GetHashCode()
+ {
+ return this.BoundLocal.GetHashCode();
+ }
+ public override bool Equals(object obj)
+ {
+ LocalBinding lb = obj as LocalBinding;
+ if (lb != null)
+ return this.BoundLocal.Equals(lb.BoundLocal);
+ else
+ return this.BoundLocal.Equals(obj);
+ }
+ int IUniqueKey.UniqueId
+ {
+ get { return this.BoundLocal.UniqueKey; }
+ }
+ }
+#endif
+ /// <summary>
+ /// A named container of types and nested namespaces.
+ /// The name of the container implicitly qualifies the names of the contained types and namespaces.
+ /// </summary>
+ public class Namespace : Member
+ {
+ /// <summary>The FullName of the namespace in the form of an Identifier rather than in the form of a string.</summary>
+ public Identifier FullNameId;
+#if !MinimalReader
+ /// <summary>
+ /// Provides alternative names for types and nested namespaces. Useful for introducing shorter names or for resolving name clashes.
+ /// The names should be added to the scope associated with this namespace.
+ /// </summary>
+ public AliasDefinitionList AliasDefinitions;
+ /// <summary>
+ /// The list of namespaces that are fully contained inside this namespace.
+ /// </summary>
+ public NamespaceList NestedNamespaces;
+ /// <summary>
+ /// The Universal Resource Identifier that should be associated with all declarations inside this namespace.
+ /// Typically used when the types inside the namespace are serialized as an XML Schema Definition. (XSD)
+ /// </summary>
+ public Identifier URI;
+ /// <summary>
+ /// The list of the namespaces of types that should be imported into the scope associated with this namespace.
+ /// </summary>
+ public UsedNamespaceList UsedNamespaces;
+#endif
+ /// <summary>
+ /// A delegate that is called the first time Types is accessed. Provides for incremental construction of the namespace node.
+ /// </summary>
+ public TypeProvider ProvideTypes;
+ /// <summary>
+ /// Opaque information passed as a parameter to the delegate in ProvideTypes. Typically used to associate this namespace
+ /// instance with a helper object.
+ /// </summary>
+ public object ProviderHandle;
+ /// <summary>
+ /// A method that fills in the Types property of the given namespace. Must not leave Types null.
+ /// </summary>
+ public delegate void TypeProvider(Namespace @namespace, object handle);
+
+ protected string fullName;
+ protected TypeNodeList types;
+
+ public Namespace()
+ : base(NodeType.Namespace)
+ {
+ }
+ public Namespace(Identifier name)
+ : base(NodeType.Namespace)
+ {
+ this.Name = name;
+ this.FullNameId = name;
+ if (name != null)
+ this.fullName = name.ToString();
+ }
+#if !MinimalReader
+ public Namespace(Identifier name, TypeProvider provideTypes, object providerHandle)
+ : base(NodeType.Namespace)
+ {
+ this.Name = name;
+ this.FullNameId = name;
+ if (name != null)
+ this.fullName = name.ToString();
+ this.ProvideTypes = provideTypes;
+ this.ProviderHandle = providerHandle;
+ }
+ public Namespace(Identifier name, Identifier fullName, AliasDefinitionList aliasDefinitions, UsedNamespaceList usedNamespaces,
+ NamespaceList nestedNamespaces, TypeNodeList types)
+ : base(NodeType.Namespace)
+ {
+ this.Name = name;
+ this.FullNameId = fullName;
+ if (fullName != null)
+ this.fullName = fullName.ToString();
+ this.AliasDefinitions = aliasDefinitions;
+ this.NestedNamespaces = nestedNamespaces;
+ this.Types = types;
+ this.UsedNamespaces = usedNamespaces;
+ }
+#endif
+ public override string/*!*/ FullName
+ {
+ get { return this.fullName == null ? "" : this.fullName; }
+ }
+ public override bool IsAssembly { get { return false; } }
+ public override bool IsCompilerControlled { get { return false; } }
+ public override bool IsFamily { get { return false; } }
+ public override bool IsFamilyAndAssembly { get { return false; } }
+ public override bool IsFamilyOrAssembly { get { return false; } }
+ public override bool IsPrivate { get { return !this.IsPublic; } }
+ public override bool IsPublic { get { return this.isPublic; } }
+ protected internal bool isPublic;
+ public override bool IsSpecialName { get { return false; } }
+ public override bool IsStatic { get { return false; } }
+ public override bool IsVisibleOutsideAssembly { get { return false; } }
+ /// <summary>
+ /// The list of types contained inside this namespace. If the value of Types is null and the value of ProvideTypes is not null, the
+ /// TypeProvider delegate is called to fill in the value of this property.
+ /// </summary>
+ public TypeNodeList Types
+ {
+ get
+ {
+ if (this.types == null)
+ if (this.ProvideTypes != null)
+ lock (this)
+ {
+ if (this.types == null)
+ {
+ this.ProvideTypes(this, this.ProviderHandle);
+ }
+ }
+ else
+ this.types = new TypeNodeList();
+ return this.types;
+ }
+ set
+ {
+ this.types = value;
+ }
+ }
+ }
+#if !MinimalReader
+ /// <summary>
+ /// The root node of an Abstract Syntax Tree. Typically corresponds to multiple source files compiled to form a single target.
+ /// </summary>
+ public class Compilation : Node
+ {
+ /// <summary>
+ /// The compilation parameters that are used for this compilation.
+ /// </summary>
+ public System.CodeDom.Compiler.CompilerParameters CompilerParameters;
+ /// <summary>
+ /// The target code object that is produced as a result of this compilation.
+ /// </summary>
+ public Module TargetModule;
+ /// <summary>
+ /// A list of all the compilation units (typically source files) that make up this compilation.
+ /// </summary>
+ public CompilationUnitList CompilationUnits;
+ /// <summary>
+ /// A scope for symbols that belong to the compilation as a whole. No C# equivalent. Null if not applicable.
+ /// </summary>
+ public Scope GlobalScope;
+ /// <summary>
+ /// A list of compilations that produce assemblies and modules that are referenced by this compilation and hence need to be
+ /// compiled before this Compilation is compiled. This list is not intended to include already compiled framework assemblies
+ /// such as system.dll.
+ /// </summary>
+ public CompilationList ReferencedCompilations;
+ public DateTime LastModified = DateTime.Now;
+ public DateTime LastCompiled = DateTime.MinValue;
+
+ public Compilation()
+ : base(NodeType.Compilation)
+ {
+ }
+ public Compilation(Module targetModule, CompilationUnitList compilationUnits, System.CodeDom.Compiler.CompilerParameters compilerParameters, Scope globalScope)
+ : base(NodeType.Compilation)
+ {
+ this.CompilationUnits = compilationUnits;
+ this.TargetModule = targetModule;
+ this.CompilerParameters = compilerParameters;
+ this.GlobalScope = globalScope;
+ }
+ public virtual Compilation CloneCompilationUnits()
+ {
+ Compilation clone = (Compilation)base.Clone();
+ CompilationUnitList cus = this.CompilationUnits;
+ if (cus != null)
+ {
+ clone.CompilationUnits = cus = cus.Clone();
+ for (int i = 0, n = cus.Count; i < n; i++)
+ {
+ CompilationUnit cu = cus[i];
+ if (cu == null) continue;
+ cus[i] = cu = (CompilationUnit)cu.Clone();
+ cu.Compilation = clone;
+ cu.Nodes = null;
+ }
+ }
+ return clone;
+ }
+ }
+ /// <summary>
+ /// The root node of an Abstract Syntax Tree. Corresponds to the starting production of the syntax. Equivalent to C# compilation-unit.
+ /// Typically a compilation unit corresponds to a single source file.
+ /// </summary>
+ public class CompilationUnit : Node
+ {
+ /// <summary>
+ /// An identifier that can be used to retrieve the source text of the compilation unit.
+ /// </summary>
+ public Identifier Name;
+ /// <summary>
+ /// An anonymous (name is Identifier.Empty) namespace holding types and nested namespaces.
+ /// </summary>
+ public NodeList Nodes;
+ /// <summary>
+ /// The preprocessor symbols that are to treated as defined when compiling this CompilationUnit into the TargetModule.
+ /// </summary>
+ public Hashtable PreprocessorDefinedSymbols;
+ /// <summary>
+ /// Pragma warning information.
+ /// </summary>
+ public TrivialHashtable PragmaWarnInformation;
+ /// <summary>
+ /// The compilation of which this unit forms a part.
+ /// </summary>
+ public Compilation Compilation;
+
+ public CompilationUnit()
+ : base(NodeType.CompilationUnit)
+ {
+ }
+ public CompilationUnit(Identifier name)
+ : base(NodeType.CompilationUnit)
+ {
+ this.Name = name;
+ }
+ }
+ public class CompilationUnitSnippet : CompilationUnit
+ {
+ public DateTime LastModified = DateTime.Now;
+ public IParserFactory ParserFactory;
+ public Method ChangedMethod;
+ public int OriginalEndPosOfChangedMethod;
+
+ public CompilationUnitSnippet()
+ {
+ this.NodeType = NodeType.CompilationUnitSnippet;
+ }
+ public CompilationUnitSnippet(Identifier name, IParserFactory parserFactory, SourceContext sctx)
+ {
+ this.NodeType = NodeType.CompilationUnitSnippet;
+ this.Name = name;
+ this.ParserFactory = parserFactory;
+ this.SourceContext = sctx;
+ }
+ }
+ public abstract class Composer
+ {
+ public abstract Node Compose(Node node, Composer context, bool hasContextReference, Class scope);
+ private class NullComposer : Composer
+ {
+ public override Node Compose(Node node, Composer context, bool hasContextReference, Class scope)
+ {
+ return node;
+ }
+ }
+ public static readonly Composer Null = new NullComposer();
+ }
+ public class Composition : Expression
+ {
+ public Expression Expression;
+ public Composer Composer;
+ public Class Scope;
+ public Composition(Expression exp, Composer composer, Class scope)
+ : base(NodeType.Composition)
+ {
+ this.Expression = exp;
+ this.Composer = composer;
+ this.Scope = scope;
+ if (exp != null) this.Type = exp.Type;
+ }
+ }
+#endif
+#if ExtendedRuntime
+ // query nodes
+ public class QueryAlias: QueryExpression{
+ public Identifier Name;
+ public Expression Expression;
+ public QueryAlias(): base(NodeType.QueryAlias){
+ }
+ }
+ public abstract class Accessor{
+ }
+ public class MemberAccessor: Accessor{
+ public Member Member;
+ public TypeNode Type;
+ public bool Yield;
+ public Accessor Next;
+ public MemberAccessor(Member member){
+ this.Member = member;
+ }
+ }
+ public class SequenceAccessor: Accessor{
+ public ArrayList Accessors; // member accessors only
+ public SequenceAccessor(){
+ this.Accessors = new ArrayList();
+ }
+ }
+ public class SwitchAccessor: Accessor{
+ public TypeUnion Type;
+ public Hashtable Accessors; // key == type
+ public SwitchAccessor(){
+ this.Accessors = new Hashtable();
+ }
+ }
+ public enum Cardinality{
+ None, // reference type
+ One, // !
+ ZeroOrOne, // ?
+ OneOrMore, // +
+ ZeroOrMore // *
+ }
+ public class QueryAxis: QueryExpression{
+ public Expression Source;
+ public bool IsDescendant;
+ public Identifier Name;
+ public Identifier Namespace;
+ public TypeNode TypeTest;
+ public Accessor AccessPlan;
+ public Cardinality Cardinality;
+ public int YieldCount;
+ public TypeNodeList YieldTypes;
+ public bool IsCyclic;
+ public bool IsIterative;
+ public QueryAxis (Expression source, bool isDescendant, Identifier name, TypeNode typeTest)
+ : base(NodeType.QueryAxis){
+ this.Source = source;
+ this.IsDescendant = isDescendant;
+ this.Name = name;
+ this.TypeTest = typeTest;
+ }
+ }
+ public class QueryAggregate: QueryExpression{
+ public Identifier Name;
+ public TypeNode AggregateType;
+ public Expression Expression;
+ public ContextScope Context;
+ public QueryGroupBy Group;
+ public QueryAggregate(): base(NodeType.QueryAggregate){
+ }
+ }
+ public class ContextScope{
+ public ContextScope Previous;
+ public TypeNode Type;
+ public Expression Target;
+ public Expression Position;
+ public Block PreFilter;
+ public Block PostFilter;
+ public ContextScope(ContextScope previous, TypeNode type){
+ this.Previous = previous;
+ this.Type = type;
+ }
+ }
+ public class QueryContext: QueryExpression{
+ public ContextScope Scope;
+ public QueryContext()
+ : base(NodeType.QueryContext){
+ }
+ public QueryContext(ContextScope scope): base(NodeType.QueryContext){
+ this.Scope = scope;
+ if (scope != null) this.Type = scope.Type;
+ }
+ }
+ public class QueryDelete: QueryExpression{
+ public Expression Source;
+ public Expression Target;
+ public ContextScope Context;
+ public Expression SourceEnumerable;
+ public QueryDelete(): base(NodeType.QueryDelete){
+ }
+ }
+ public class QueryDistinct: QueryExpression{
+ public Expression Source;
+ public ContextScope Context;
+ public QueryGroupBy Group;
+ public Expression GroupTarget;
+ public QueryDistinct(): base(NodeType.QueryDistinct){
+ }
+ }
+ public class QueryDifference: QueryExpression{
+ public Expression LeftSource;
+ public Expression RightSource;
+ public QueryDifference() : base(NodeType.QueryDifference){
+ }
+ }
+ public class QueryExists: QueryExpression{
+ public Expression Source;
+ public QueryExists() : base(NodeType.QueryExists){
+ }
+ }
+ public abstract class QueryExpression: Expression{
+ protected QueryExpression(NodeType nt): base(nt){
+ }
+ }
+ public class QueryFilter: QueryExpression{
+ public Expression Source;
+ public Expression Expression;
+ public ContextScope Context;
+ public QueryFilter(): base(NodeType.QueryFilter){
+ }
+ public QueryFilter (Expression source, Expression filter): this(){
+ this.Source = source;
+ this.Expression = filter;
+ }
+ }
+ public class QueryYielder: Statement{
+ public Expression Source;
+ public Expression Target;
+ public Expression State;
+ public Block Body;
+ public QueryYielder(): base(NodeType.QueryYielder){
+ }
+ }
+ public class QueryGeneratedType: Statement{
+ public TypeNode Type;
+ public QueryGeneratedType(TypeNode type): base(NodeType.QueryGeneratedType){
+ this.Type = type;
+ }
+ }
+ public class QueryGroupBy: QueryExpression{
+ public Expression Source;
+ public ContextScope GroupContext;
+ public ExpressionList GroupList;
+ public ExpressionList AggregateList;
+ public Expression Having;
+ public ContextScope HavingContext;
+ public QueryGroupBy(): base(NodeType.QueryGroupBy){
+ this.GroupList = new ExpressionList();
+ this.AggregateList = new ExpressionList();
+ }
+ }
+ public class QueryInsert: QueryExpression{
+ public Expression Location;
+ public QueryInsertPosition Position;
+ public ExpressionList InsertList;
+ public ExpressionList HintList;
+ public ContextScope Context;
+ public bool IsBracket;
+ public QueryInsert(): base(NodeType.QueryInsert){
+ this.InsertList = new ExpressionList();
+ this.HintList = new ExpressionList();
+ }
+ }
+ public enum QueryInsertPosition{
+ After,
+ At,
+ Before,
+ First,
+ In,
+ Last
+ }
+ public class QueryIntersection: QueryExpression{
+ public Expression LeftSource;
+ public Expression RightSource;
+ public QueryIntersection(): base(NodeType.QueryIntersection){
+ }
+ }
+ public class QueryScope: BlockScope{
+ public QueryScope(Scope/*!*/ parentScope)
+ : base(parentScope, null) {
+ }
+ }
+ public class QueryIterator: QueryAlias{
+ public TypeNode ElementType;
+ public TypeNode TypeExpression;
+ public ExpressionList HintList;
+ public QueryIterator(): base(){
+ this.NodeType = NodeType.QueryIterator;
+ this.HintList = new ExpressionList();
+ }
+ }
+ public class QueryJoin: QueryExpression{
+ public Expression LeftOperand;
+ public Expression RightOperand;
+ public QueryJoinType JoinType;
+ public Expression JoinExpression;
+ public ContextScope JoinContext;
+ public QueryJoin(): base(NodeType.QueryJoin){
+ }
+ }
+ public enum QueryJoinType{
+ Inner,
+ LeftOuter,
+ RightOuter,
+ FullOuter
+ }
+ public class QueryLimit: QueryExpression{
+ public Expression Source;
+ public Expression Expression;
+ public bool IsPercent;
+ public bool IsWithTies;
+ public QueryLimit(): base(NodeType.QueryLimit){
+ }
+ }
+ public class QueryOrderBy: QueryExpression{
+ public Expression Source;
+ public ContextScope Context;
+ public ExpressionList OrderList;
+ public QueryOrderBy(): base(NodeType.QueryOrderBy){
+ this.OrderList = new ExpressionList();
+ }
+ }
+ public enum QueryOrderType{
+ Ascending,
+ Descending,
+ Document
+ }
+ public class QueryOrderItem: QueryExpression{
+ public Expression Expression;
+ public QueryOrderType OrderType = QueryOrderType.Ascending;
+ public QueryOrderItem(): base(NodeType.QueryOrderItem){
+ }
+ }
+ public class QueryPosition: QueryExpression{
+ public ContextScope Context;
+ public QueryPosition(ContextScope context): base(NodeType.QueryPosition){
+ this.Context = context;
+ this.Type = CoreSystemTypes.Int32;
+ }
+ public static readonly Identifier Id = Identifier.For("position");
+ }
+ public class QueryProject: QueryExpression{
+ public Expression Source;
+ public ContextScope Context;
+ public ExpressionList ProjectionList;
+ public TypeNode ProjectedType;
+ public MemberList Members;
+ public QueryProject(): base(NodeType.QueryProject){
+ this.ProjectionList = new ExpressionList();
+ }
+ }
+ public class QueryQuantifiedExpression: QueryExpression{
+ public QueryQuantifier Left;
+ public QueryQuantifier Right;
+ public Expression Expression;
+ public QueryQuantifiedExpression(): base(NodeType.QueryQuantifiedExpression){
+ }
+ }
+ public class QueryQuantifier: QueryExpression{
+ public Expression Expression;
+ public Expression Target;
+ public QueryQuantifier(NodeType nt): base(nt){
+ }
+ }
+ public class QuerySingleton: QueryExpression{
+ public Expression Source;
+ public QuerySingleton(): base(NodeType.QuerySingleton){
+ }
+ }
+ public class QuerySelect: QueryExpression{
+ public Expression Source;
+ public QueryCursorDirection Direction;
+ public QueryCursorAccess Access;
+ public QuerySelect(Expression source): base(NodeType.QuerySelect){
+ if (source != null){
+ this.Source = source;
+ this.Type = source.Type;
+ }
+ }
+ }
+ public enum QueryCursorDirection{
+ ForwardOnly,
+ Scrollable
+ }
+ public enum QueryCursorAccess{
+ ReadOnly,
+ Updatable
+ }
+
+ public abstract class QueryStatement: Statement{
+ protected QueryStatement(NodeType nt): base(nt){
+ }
+ }
+ public class QueryTypeFilter: QueryExpression{
+ public Expression Source;
+ public TypeNode Constraint;
+ public QueryTypeFilter(): base(NodeType.QueryTypeFilter){
+ }
+ }
+ public class QueryUnion: QueryExpression{
+ public Expression LeftSource;
+ public Expression RightSource;
+ public QueryUnion() : base(NodeType.QueryUnion){
+ }
+ }
+ public class QueryUpdate: QueryExpression{
+ public Expression Source;
+ public ExpressionList UpdateList;
+ public ContextScope Context;
+ public QueryUpdate() : base(NodeType.QueryUpdate){
+ this.UpdateList = new ExpressionList();
+ }
+ }
+ public class QueryTransact: Statement{
+ public Expression Source;
+ public Expression Isolation;
+ public Block Body;
+ public Block CommitBody;
+ public Block RollbackBody;
+ public Expression Transaction;
+ public QueryTransact(): base(NodeType.QueryTransact){
+ }
+ }
+ public class QueryCommit: Statement{
+ public QueryCommit(): base(NodeType.QueryCommit){
+ }
+ }
+ public class QueryRollback: Statement{
+ public QueryRollback(): base(NodeType.QueryRollback){
+ }
+ }
+#endif
+#if !MinimalReader
+ /// <summary>
+ /// An object that knows how to produce a particular scope's view of a type.
+ /// </summary>
+ public class TypeViewer
+ {
+ /// <summary>
+ /// Return a scope's view of the argument type, where the scope's view is represented
+ /// by a type viewer.
+ /// [The identity function, except for dialects (e.g. Extensible Sing#) that allow
+ /// extensions and differing views of types].
+ /// Defined as a static method to allow the type viewer to be null,
+ /// meaning an identity-function view.
+ /// </summary>
+ public static TypeNode/*!*/ GetTypeView(TypeViewer typeViewer, TypeNode/*!*/ type)
+ {
+ return typeViewer == null ? type.EffectiveTypeNode : typeViewer.GetTypeView(type);
+ }
+
+ /// <summary>
+ /// Return the typeViewer's view of the argument type. Overridden by subclasses
+ /// that support non-identity-function type viewers, e.g. Extensible Sing#.
+ /// </summary>
+ protected virtual TypeNode/*!*/ GetTypeView(TypeNode/*!*/ type)
+ {
+ return type.EffectiveTypeNode;
+ }
+ }
+#endif
+#if WHIDBEY
+ static
+#endif
+ class PlatformHelpers
+ {
+ internal static bool TryParseInt32(String s, out Int32 result)
+ {
+#if WHIDBEY
+ return Int32.TryParse(s, NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out result);
+#else
+ result = 0;
+ bool succeeded = false;
+ try {
+ result = Int32.Parse(s, NumberFormatInfo.InvariantInfo);
+ succeeded = true;
+ }catch(ArgumentException){
+ }catch(FormatException){
+ }catch(OverflowException){}
+ return succeeded;
+#endif
+ }
+ internal static int StringCompareOrdinalIgnoreCase(string strA, int indexA, string strB, int indexB, int length)
+ {
+#if WHIDBEY
+ return string.Compare(strA, indexA, strB, indexB, length, StringComparison.OrdinalIgnoreCase);
+#else
+ return string.Compare(strA, indexA, strB, indexB, length, true, CultureInfo.InvariantCulture);
+#endif
+ }
+ internal static int StringCompareOrdinalIgnoreCase(string strA, string strB)
+ {
+#if WHIDBEY
+ return string.Compare(strA, strB, StringComparison.OrdinalIgnoreCase);
+#else
+ return string.Compare(strA, strB, true, CultureInfo.InvariantCulture);
+#endif
+ }
+ }
+#if FxCop
+ public class CatchNode : Statement{
+ private Block block;
+ private TypeNode type;
+ private Expression variable;
+ private Filter filter;
+ internal int handlerEnd;
+ internal CatchNode()
+ : base(NodeType.Catch){
+ }
+ internal CatchNode(Block block, Expression variable, TypeNode type)
+ : this(block, variable, type, null){
+ }
+ internal CatchNode(Block block, Expression variable, TypeNode type, Filter filter)
+ : base(NodeType.Catch){
+ this.block = block;
+ this.variable = variable;
+ this.type = type;
+ this.filter = filter;
+ }
+ public Block Block{
+ get{return this.block;}
+ internal set{this.block = value;}
+ }
+ public Filter Filter{
+ get{return this.filter;}
+ internal set{this.filter = value;}
+ }
+ public TypeNode Type{
+ get{return this.type;}
+ internal set{this.type = value;}
+ }
+ public Expression Variable{
+ get{return this.variable;}
+ internal set{this.variable = value;}
+ }
+ }
+ public class FinallyNode : Statement{
+ private Block block;
+ internal int handlerEnd;
+ internal FinallyNode()
+ : base(NodeType.Finally){
+ }
+ internal FinallyNode(Block block)
+ : base(NodeType.Finally){
+ this.block = block;
+ }
+ public Block Block{
+ get{return this.block;}
+ internal set{this.block = value;}
+ }
+ }
+ public class TryNode : Statement {
+ private CatchNodeCollection catchers = new CatchNodeCollection();
+ private FaultHandler faultHandler;
+ private FinallyNode finallyClause;
+ private Block block;
+ internal TryNode()
+ : base(NodeType.Try) {
+ }
+ internal TryNode(Block block, CatchNodeCollection catchers, FaultHandler faultHandler, FinallyNode @finally)
+ : base(NodeType.Try) {
+ this.catchers = catchers;
+ this.faultHandler = faultHandler;
+ this.finallyClause = @finally;
+ this.block = block;
+ }
+ internal int tryEnd;
+ internal int handlersEnd;
+ public CatchNodeCollection Catchers {
+ get { return this.catchers; }
+ internal set { this.catchers = value; }
+ }
+ public FaultHandler FaultHandler {
+ get { return this.faultHandler; }
+ internal set { this.faultHandler = value; }
+ }
+ public FinallyNode Finally {
+ get { return this.finallyClause; }
+ internal set { this.finallyClause = value; }
+ }
+ public Block Block {
+ [DebuggerStepThrough] get { return this.block; }
+ [DebuggerStepThrough] internal set { this.block = value; }
+ }
+ }
+ public abstract class FormatOptions
+ {
+ internal Options m_options;
+
+ protected FormatOptions() { }
+
+ internal void SetOptions(Options options, bool enable)
+ {
+ if (enable)
+ {
+ this.m_options |= options;
+ return;
+ }
+ this.m_options &= ~options;
+ }
+
+ internal bool IsSet(Options options)
+ {
+ return (this.m_options & options) == options;
+ }
+
+ [Flags]
+ internal enum Options
+ {
+ None = 0x0,
+ InsertSpacesBetweenParameters = 0x1,
+ InsertSpacesBetweenTypeParameters = 0x2,
+ InsertSpacesBetweenMethodTypeParameters = 0x4,
+ ShowGenericTypeArity = 0x8,
+ ShowGenericMethodTypeParameterNames = 0x10,
+ ShowGenericTypeParameterNames = 0x20,
+ ShowTypeModifiers = 0x40,
+ ShowParameterNames = 0x80
+ }
+ }
+ internal class MemberFormat : FormatOptions
+ {
+ TypeFormat m_declaringTypeFormat;
+ TypeFormat m_returnTypeFormat;
+ ParameterFormat m_parameterFormat;
+
+ public MemberFormat()
+ {
+ this.m_declaringTypeFormat = new TypeFormat();
+ this.m_returnTypeFormat = new TypeFormat();
+ this.m_parameterFormat = new ParameterFormat();
+ }
+
+ public TypeFormat Type
+ {
+ get { return this.m_declaringTypeFormat; }
+ }
+
+ public TypeFormat ReturnType
+ {
+ get { return this.m_returnTypeFormat; }
+ }
+
+ public ParameterFormat Parameters
+ {
+ get { return this.m_parameterFormat; }
+ }
+
+ public bool ShowGenericMethodTypeParameterNames
+ {
+ get { return IsSet(Options.ShowGenericMethodTypeParameterNames); }
+ set { SetOptions(Options.ShowGenericMethodTypeParameterNames, value); }
+ }
+
+ public bool InsertSpacesBetweenMethodTypeParameters
+ {
+ get { return IsSet(Options.InsertSpacesBetweenMethodTypeParameters); }
+ set { SetOptions(Options.InsertSpacesBetweenMethodTypeParameters, value); }
+ }
+ }
+ internal class ParameterFormat : TypeFormat
+ {
+ public ParameterFormat() { }
+
+ public bool InsertSpacesBetweenParameters
+ {
+ get { return IsSet(Options.InsertSpacesBetweenParameters); }
+ set { SetOptions(Options.InsertSpacesBetweenParameters, value); }
+ }
+
+ public bool ShowParameterNames
+ {
+ get { return IsSet(Options.ShowParameterNames); }
+ set { SetOptions(Options.ShowParameterNames, value); }
+ }
+ }
+ internal class TypeFormat : FormatOptions
+ {
+ private TypeNameFormat m_typeName;
+ public TypeFormat() { }
+
+ public TypeFormat Clone()
+ {
+ TypeFormat clone = new TypeFormat();
+ clone.m_typeName = this.m_typeName;
+ clone.m_options = this.m_options;
+ return clone;
+ }
+
+ public bool InsertSpacesBetweenTypeParameters
+ {
+ get { return IsSet(Options.InsertSpacesBetweenTypeParameters); }
+ set { SetOptions(Options.InsertSpacesBetweenTypeParameters, value); }
+ }
+
+ public bool ShowGenericTypeArity
+ {
+ get { return IsSet(Options.ShowGenericTypeArity); }
+ set { SetOptions(Options.ShowGenericTypeArity, value); }
+ }
+
+ public bool ShowGenericTypeParameterNames
+ {
+ get { return IsSet(Options.ShowGenericTypeParameterNames); }
+ set { SetOptions(Options.ShowGenericTypeParameterNames, value); }
+ }
+
+ public bool ShowTypeModifiers
+ {
+ get { return IsSet(Options.ShowTypeModifiers); }
+ set { SetOptions(Options.ShowTypeModifiers, value); }
+ }
+
+ public TypeNameFormat TypeName
+ {
+ get { return this.m_typeName; }
+ set { this.m_typeName = value; }
+ }
+ }
+ internal enum TypeNameFormat
+ {
+ None = 0,
+ InnermostNested,
+ Short,
+ FullyQualified
+ }
+#endif
+}