X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fsupport.cs;h=28a2cf4d15b1362062b023e2ef6a7bfdfc25cfdc;hb=9aa6670554223e895c24ce7c331c93b0d57e8816;hp=a9e33b178bf7a976a87c88e6fa538b609e068ac4;hpb=286afd095ba609a91a5fd0257666219eb086008c;p=mono.git diff --git a/mcs/mcs/support.cs b/mcs/mcs/support.cs index a9e33b178bf..28a2cf4d15b 100644 --- a/mcs/mcs/support.cs +++ b/mcs/mcs/support.cs @@ -4,201 +4,124 @@ // // Author: // Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@gmail.com) // // Copyright 2001 Ximian, Inc (http://www.ximian.com) -// Copyright 2003-2008 Novell, Inc +// Copyright 2003-2009 Novell, Inc // using System; using System.IO; using System.Text; -using System.Reflection; -using System.Collections; -using System.Reflection.Emit; -using System.Globalization; +using System.Collections.Generic; namespace Mono.CSharp { -#if GMCS_SOURCE - public class ReflectionConstraints : GenericConstraints + sealed class ReferenceEquality : IEqualityComparer where T : class { - GenericParameterAttributes attrs; - Type base_type; - Type class_constraint; - Type[] iface_constraints; - string name; + public static readonly IEqualityComparer Default = new ReferenceEquality (); - public static GenericConstraints GetConstraints (Type t) + private ReferenceEquality () { - Type [] constraints = t.GetGenericParameterConstraints (); - GenericParameterAttributes attrs = t.GenericParameterAttributes; - if (constraints.Length == 0 && attrs == GenericParameterAttributes.None) - return null; - return new ReflectionConstraints (t.Name, constraints, attrs); } - private ReflectionConstraints (string name, Type [] constraints, GenericParameterAttributes attrs) + public bool Equals (T x, T y) { - this.name = name; - this.attrs = attrs; - - if ((constraints.Length > 0) && !constraints [0].IsInterface) { - class_constraint = constraints [0]; - iface_constraints = new Type [constraints.Length - 1]; - Array.Copy (constraints, 1, iface_constraints, 0, constraints.Length - 1); - } else - iface_constraints = constraints; - - if (HasValueTypeConstraint) - base_type = TypeManager.value_type; - else if (class_constraint != null) - base_type = class_constraint; - else - base_type = TypeManager.object_type; + return ReferenceEquals (x, y); } - public override string TypeParameter { - get { return name; } + public int GetHashCode (T obj) + { + return System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode (obj); } + } - public override GenericParameterAttributes Attributes { - get { return attrs; } + public class Tuple : IEquatable> + { + public Tuple (T1 item1, T2 item2) + { + Item1 = item1; + Item2 = item2; } - public override Type ClassConstraint { - get { return class_constraint; } - } + public T1 Item1 { get; private set; } + public T2 Item2 { get; private set; } - public override Type EffectiveBaseClass { - get { return base_type; } + public override int GetHashCode () + { + return Item1.GetHashCode () ^ Item2.GetHashCode (); } - public override Type[] InterfaceConstraints { - get { return iface_constraints; } - } - } -#endif + #region IEquatable> Members - class PtrHashtable : Hashtable { - sealed class PtrComparer : IComparer -#if NET_2_0 - , IEqualityComparer -#endif + public bool Equals (Tuple other) { - private PtrComparer () {} - - public static PtrComparer Instance = new PtrComparer (); - - public int Compare (object x, object y) - { - if (x == y) - return 0; - else - return 1; - } -#if NET_2_0 - bool IEqualityComparer.Equals (object x, object y) - { - return x == y; - } - - int IEqualityComparer.GetHashCode (object obj) - { - return obj.GetHashCode (); - } -#endif - + return EqualityComparer.Default.Equals (Item1, other.Item1) && + EqualityComparer.Default.Equals (Item2, other.Item2); } -#if NET_2_0 - public PtrHashtable () : base (PtrComparer.Instance) {} -#else - public PtrHashtable () - { - comparer = PtrComparer.Instance; - } -#endif + #endregion + } -#if MS_COMPATIBLE - // - // Workaround System.InvalidOperationException for enums - // - protected override int GetHash (object key) + public class Tuple : IEquatable> + { + public Tuple (T1 item1, T2 item2, T3 item3) { - TypeBuilder tb = key as TypeBuilder; - if (tb != null && tb.BaseType == TypeManager.enum_type) - key = tb.BaseType; - - return base.GetHash (key); + Item1 = item1; + Item2 = item2; + Item3 = item3; } -#endif - } - /* - * Hashtable whose keys are character arrays with the same length - */ - class CharArrayHashtable : Hashtable { - sealed class ArrComparer : IComparer { - private int len; - - public ArrComparer (int len) { - this.len = len; - } + public T1 Item1 { get; private set; } + public T2 Item2 { get; private set; } + public T3 Item3 { get; private set; } - public int Compare (object x, object y) - { - char[] a = (char[])x; - char[] b = (char[])y; - - for (int i = 0; i < len; ++i) - if (a [i] != b [i]) - return 1; - return 0; - } + public override int GetHashCode () + { + return Item1.GetHashCode () ^ Item2.GetHashCode () ^ Item3.GetHashCode (); } - private int len; + #region IEquatable> Members - protected override int GetHash (Object key) + public bool Equals (Tuple other) { - char[] arr = (char[])key; - int h = 0; + return EqualityComparer.Default.Equals (Item1, other.Item1) && + EqualityComparer.Default.Equals (Item2, other.Item2) && + EqualityComparer.Default.Equals (Item3, other.Item3); + } - for (int i = 0; i < len; ++i) - h = (h << 5) - h + arr [i]; + #endregion + } - return h; + static class Tuple + { + public static Tuple Create (T1 item1, T2 item2) + { + return new Tuple (item1, item2); } - public CharArrayHashtable (int len) + public static Tuple Create (T1 item1, T2 item2, T3 item3) { - this.len = len; - comparer = new ArrComparer (len); + return new Tuple (item1, item2, item3); } } - struct Pair { - public object First; - public object Second; - - public Pair (object f, object s) + static class ArrayComparer + { + public static bool IsEqual (T[] array1, T[] array2) { - First = f; - Second = s; - } - } + if (array1 == null || array2 == null) + return array1 == array2; - public class Accessors { - public Accessor get_or_add; - public Accessor set_or_remove; + var eq = EqualityComparer.Default; - // was 'set' declared before 'get'? was 'remove' declared before 'add'? - public bool declared_in_reverse; + for (int i = 0; i < array1.Length; ++i) { + if (!eq.Equals (array1[i], array2[i])) { + return false; + } + } - public Accessors (Accessor get_or_add, Accessor set_or_remove) - { - this.get_or_add = get_or_add; - this.set_or_remove = set_or_remove; + return true; } } @@ -209,36 +132,43 @@ namespace Mono.CSharp { /// but if the seek is too far, it may read the underly /// stream all over from the beginning. /// - public class SeekableStreamReader + public class SeekableStreamReader : IDisposable { - const int default_average_read_length = 1024; - const int buffer_read_length_spans = 3; - - TextReader reader; + StreamReader reader; Stream stream; - Encoding encoding; - char[] buffer; - int average_read_length; + static char[] buffer; + int read_ahead_length; // the length of read buffer int buffer_start; // in chars - int char_count; // count buffer[] valid characters + int char_count; // count of filled characters in buffer[] int pos; // index into buffer[] - void ResetStream (int read_length_inc) + public SeekableStreamReader (Stream stream, Encoding encoding) { - average_read_length += read_length_inc; - stream.Position = 0; + this.stream = stream; + + const int default_read_ahead = 2048; + InitializeStream (default_read_ahead); reader = new StreamReader (stream, encoding, true); - buffer = new char [average_read_length * buffer_read_length_spans]; - buffer_start = char_count = pos = 0; } - public SeekableStreamReader (Stream stream, Encoding encoding) + public void Dispose () { - this.stream = stream; - this.encoding = encoding; + // Needed to release stream reader buffers + reader.Dispose (); + } + + void InitializeStream (int read_length_inc) + { + read_ahead_length += read_length_inc; + + int required_buffer_size = read_ahead_length * 2; + + if (buffer == null || buffer.Length < required_buffer_size) + buffer = new char [required_buffer_size]; - ResetStream (default_average_read_length); + stream.Position = 0; + buffer_start = char_count = pos = 0; } /// @@ -249,12 +179,25 @@ namespace Mono.CSharp { /// a correlation between them. /// public int Position { - get { return buffer_start + pos; } + get { + return buffer_start + pos; + } set { - // If the lookahead was too small, re-read from the beginning. Increase the buffer size while we're at it - if (value < buffer_start) - ResetStream (average_read_length / 2); + // + // If the lookahead was too small, re-read from the beginning. Increase the buffer size while we're at it + // This should never happen until we are parsing some weird source code + // + if (value < buffer_start) { + InitializeStream (read_ahead_length); + + // + // Discard buffer data after underlying stream changed position + // Cannot use handy reader.DiscardBufferedData () because it for + // some strange reason resets encoding as well + // + reader = new StreamReader (stream, reader.CurrentEncoding, true); + } while (value > buffer_start + char_count) { pos = char_count; @@ -266,17 +209,26 @@ namespace Mono.CSharp { } } - private bool ReadBuffer () + bool ReadBuffer () { int slack = buffer.Length - char_count; - if (slack <= average_read_length / 2) { - // shift the buffer to make room for average_read_length number of characters - int shift = average_read_length - slack; + + // + // read_ahead_length is only half of the buffer to deal with + // reads ahead and moves back without re-reading whole buffer + // + if (slack <= read_ahead_length) { + // + // shift the buffer to make room for read_ahead_length number of characters + // + int shift = read_ahead_length - slack; Array.Copy (buffer, shift, buffer, 0, char_count - shift); + + // Update all counters pos -= shift; char_count -= shift; buffer_start += shift; - slack += shift; // slack == average_read_length + slack += shift; } char_count += reader.Read (buffer, char_count, slack); @@ -301,172 +253,6 @@ namespace Mono.CSharp { } } - public class DoubleHash { - const int DEFAULT_INITIAL_BUCKETS = 100; - - public DoubleHash () : this (DEFAULT_INITIAL_BUCKETS) {} - - public DoubleHash (int size) - { - count = size; - buckets = new Entry [size]; - } - - int count; - Entry [] buckets; - int size = 0; - - class Entry { - public object key1; - public object key2; - public int hash; - public object value; - public Entry next; - - public Entry (object key1, object key2, int hash, object value, Entry next) - { - this.key1 = key1; - this.key2 = key2; - this.hash = hash; - this.next = next; - this.value = value; - } - } - - public bool Lookup (object a, object b, out object res) - { - int h = (a.GetHashCode () ^ b.GetHashCode ()) & 0x7FFFFFFF; - - for (Entry e = buckets [h % count]; e != null; e = e.next) { - if (e.hash == h && e.key1.Equals (a) && e.key2.Equals (b)) { - res = e.value; - return true; - } - } - res = null; - return false; - } - - public void Insert (object a, object b, object value) - { - // Is it an existing one? - - int h = (a.GetHashCode () ^ b.GetHashCode ()) & 0x7FFFFFFF; - - for (Entry e = buckets [h % count]; e != null; e = e.next) { - if (e.hash == h && e.key1.Equals (a) && e.key2.Equals (b)) - e.value = value; - } - - int bucket = h % count; - buckets [bucket] = new Entry (a, b, h, value, buckets [bucket]); - - // Grow whenever we double in size - if (size++ == count) { - count <<= 1; - count ++; - - Entry [] newBuckets = new Entry [count]; - foreach (Entry root in buckets) { - Entry e = root; - while (e != null) { - int newLoc = e.hash % count; - Entry n = e.next; - e.next = newBuckets [newLoc]; - newBuckets [newLoc] = e; - e = n; - } - } - - buckets = newBuckets; - } - } - } - - class PartialMethodDefinitionInfo : MethodInfo - { - MethodOrOperator mc; - MethodAttributes attrs; - - public PartialMethodDefinitionInfo (MethodOrOperator mc) - { - this.mc = mc; - if ((mc.ModFlags & Modifiers.STATIC) != 0) - attrs = MethodAttributes.Static; - } - - public override MethodInfo GetBaseDefinition () - { - throw new NotImplementedException (); - } - - public override ICustomAttributeProvider ReturnTypeCustomAttributes - { - get { throw new NotImplementedException (); } - } - - public override MethodAttributes Attributes - { - get { return attrs; } - } - - public override MethodImplAttributes GetMethodImplementationFlags () - { - throw new NotImplementedException (); - } - - public override ParameterInfo [] GetParameters () - { - throw new NotImplementedException (); - } - - public override object Invoke (object obj, BindingFlags invokeAttr, Binder binder, object [] parameters, CultureInfo culture) - { - throw new NotImplementedException (); - } - - public override RuntimeMethodHandle MethodHandle - { - get { throw new NotImplementedException (); } - } - - public override Type DeclaringType - { - get { return mc.Parent.TypeBuilder; } - } - - public override object [] GetCustomAttributes (Type attributeType, bool inherit) - { - throw new NotImplementedException (); - } - - public override object [] GetCustomAttributes (bool inherit) - { - throw new NotImplementedException (); - } - - public override Type ReturnType { - get { - return mc.MemberType; - } - } - - public override bool IsDefined (Type attributeType, bool inherit) - { - throw new NotImplementedException (); - } - - public override string Name - { - get { return mc.Name; } - } - - public override Type ReflectedType - { - get { throw new NotImplementedException (); } - } - } - public class UnixUtils { [System.Runtime.InteropServices.DllImport ("libc", EntryPoint="isatty")] extern static int _isatty (int fd); @@ -480,4 +266,39 @@ namespace Mono.CSharp { } } } + + /// + /// An exception used to terminate the compiler resolution phase and provide completions + /// + /// + /// This is thrown when we want to return the completions or + /// terminate the completion process by AST nodes used in + /// the completion process. + /// + public class CompletionResult : Exception { + string [] result; + string base_text; + + public CompletionResult (string base_text, string [] res) + { + if (base_text == null) + throw new ArgumentNullException ("base_text"); + this.base_text = base_text; + + result = res; + Array.Sort (result); + } + + public string [] Result { + get { + return result; + } + } + + public string BaseText { + get { + return base_text; + } + } + } }