// 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 AssemblyReferenceListMicrosoft.Cci.AssemblyReferenceCollection;
using AttributeListMicrosoft.Cci.AttributeNodeCollection;
using BlockListMicrosoft.Cci.BlockCollection;
using ExpressionListMicrosoft.Cci.ExpressionCollection;
using InstructionListMicrosoft.Cci.InstructionCollection;
using Int32ListSystem.Collections.Generic.List;
using InterfaceListMicrosoft.Cci.InterfaceCollection;
using MemberListMicrosoft.Cci.MemberCollection;
using MethodListMicrosoft.Cci.MethodCollection;
using ModuleReferenceListMicrosoft.Cci.ModuleReferenceCollection;
using NamespaceListMicrosoft.Cci.NamespaceCollection;
using ParameterListMicrosoft.Cci.ParameterCollection;
using ResourceListMicrosoft.Cci.ResourceCollection;
using SecurityAttributeListMicrosoft.Cci.SecurityAttributeCollection;
using StatementListMicrosoft.Cci.StatementCollection;
using TypeNodeListMicrosoft.Cci.TypeNodeCollection;
using Win32ResourceListMicrosoft.Cci.Win32ResourceCollection;
using ModuleMicrosoft.Cci.ModuleNode;
using ClassMicrosoft.Cci.ClassNode;
using InterfaceMicrosoft.Cci.InterfaceNode;
using PropertyMicrosoft.Cci.PropertyNode;
using EventMicrosoft.Cci.EventNode;
using ReturnMicrosoft.Cci.ReturnNode;
using ThrowMicrosoft.Cci.ThrowNode;
#endif
#if UseSingularityPDB
using Microsoft.Singularity.PdbInfo;
#endif
#if CCINamespace
using CciMicrosoft.Cci;
using Microsoft.Cci.Metadata;
using MetadataMicrosoft.Cci.Metadata;
#else
using CciSystem.Compiler;
using System.Compiler.Metadata;
using MetadataSystem.Compiler.Metadata;
#endif
using System.Diagnostics;
using System.IO;
using System.Text;
#if !NoXml
using System.Xml;
#endif
using BindingFlagsSystem.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
}
|