2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / mcs / support.cs
blob8cca4a54b9cc289ce859f3cf9035be9749adc697
1 //
2 // support.cs: Support routines to work around the fact that System.Reflection.Emit
3 // can not introspect types that are being constructed
4 //
5 // Author:
6 // Miguel de Icaza (miguel@ximian.com)
7 // Marek Safar (marek.safar@gmail.com)
8 //
9 // Copyright 2001 Ximian, Inc (http://www.ximian.com)
10 // Copyright 2003-2009 Novell, Inc
13 using System;
14 using System.IO;
15 using System.Text;
16 using System.Reflection;
17 using System.Reflection.Emit;
18 using System.Globalization;
19 using System.Collections.Generic;
21 namespace Mono.CSharp {
23 class ReferenceEquality<T> : IEqualityComparer<T> where T : class
25 public static readonly IEqualityComparer<T> Default = new ReferenceEquality<T> ();
27 private ReferenceEquality ()
31 public bool Equals (T x, T y)
33 return ReferenceEquals (x, y);
36 public int GetHashCode (T obj)
38 return System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode (obj);
42 class Tuple<T1, T2>
44 public Tuple (T1 item1, T2 item2)
46 Item1 = item1;
47 Item2 = item2;
50 public T1 Item1 { get; private set; }
51 public T2 Item2 { get; private set; }
54 public class Accessors {
55 public Accessor get_or_add;
56 public Accessor set_or_remove;
58 // was 'set' declared before 'get'? was 'remove' declared before 'add'?
59 public bool declared_in_reverse;
61 public Accessors (Accessor get_or_add, Accessor set_or_remove)
63 this.get_or_add = get_or_add;
64 this.set_or_remove = set_or_remove;
68 /// <summary>
69 /// This is an arbitrarily seekable StreamReader wrapper.
70 ///
71 /// It uses a self-tuning buffer to cache the seekable data,
72 /// but if the seek is too far, it may read the underly
73 /// stream all over from the beginning.
74 /// </summary>
75 public class SeekableStreamReader : IDisposable
77 const int buffer_read_length_spans = 3;
79 TextReader reader;
80 Stream stream;
82 static char[] buffer;
83 int average_read_length;
84 int buffer_start; // in chars
85 int char_count; // count buffer[] valid characters
86 int pos; // index into buffer[]
88 public SeekableStreamReader (Stream stream, Encoding encoding)
90 this.stream = stream;
92 const int default_average_read_length = 1024;
93 InitializeStream (default_average_read_length);
94 reader = new StreamReader (stream, encoding, true);
97 public void Dispose ()
99 // Needed to release stream reader buffers
100 reader.Dispose ();
103 void InitializeStream (int read_length_inc)
105 average_read_length += read_length_inc;
107 int required_buffer_size = average_read_length * buffer_read_length_spans;
108 if (buffer == null || buffer.Length < required_buffer_size)
109 buffer = new char [required_buffer_size];
111 stream.Position = 0;
112 buffer_start = char_count = pos = 0;
115 /// <remarks>
116 /// This value corresponds to the current position in a stream of characters.
117 /// The StreamReader hides its manipulation of the underlying byte stream and all
118 /// character set/decoding issues. Thus, we cannot use this position to guess at
119 /// the corresponding position in the underlying byte stream even though there is
120 /// a correlation between them.
121 /// </remarks>
122 public int Position {
123 get { return buffer_start + pos; }
125 set {
126 // If the lookahead was too small, re-read from the beginning. Increase the buffer size while we're at it
127 if (value < buffer_start)
128 InitializeStream (average_read_length / 2);
130 while (value > buffer_start + char_count) {
131 pos = char_count;
132 if (!ReadBuffer ())
133 throw new InternalErrorException ("Seek beyond end of file: " + (buffer_start + char_count - value));
136 pos = value - buffer_start;
140 private bool ReadBuffer ()
142 int slack = buffer.Length - char_count;
143 if (slack <= average_read_length / 2) {
144 // shift the buffer to make room for average_read_length number of characters
145 int shift = average_read_length - slack;
146 Array.Copy (buffer, shift, buffer, 0, char_count - shift);
147 pos -= shift;
148 char_count -= shift;
149 buffer_start += shift;
150 slack += shift; // slack == average_read_length
153 char_count += reader.Read (buffer, char_count, slack);
155 return pos < char_count;
158 public int Peek ()
160 if ((pos >= char_count) && !ReadBuffer ())
161 return -1;
163 return buffer [pos];
166 public int Read ()
168 if ((pos >= char_count) && !ReadBuffer ())
169 return -1;
171 return buffer [pos++];
175 public class DoubleHash {
176 const int DEFAULT_INITIAL_BUCKETS = 100;
178 public DoubleHash () : this (DEFAULT_INITIAL_BUCKETS) {}
180 public DoubleHash (int size)
182 count = size;
183 buckets = new Entry [size];
186 int count;
187 Entry [] buckets;
188 int size = 0;
190 class Entry {
191 public object key1;
192 public object key2;
193 public int hash;
194 public object value;
195 public Entry next;
197 public Entry (object key1, object key2, int hash, object value, Entry next)
199 this.key1 = key1;
200 this.key2 = key2;
201 this.hash = hash;
202 this.next = next;
203 this.value = value;
207 public bool Lookup (object a, object b, out object res)
209 int h = (a.GetHashCode () ^ b.GetHashCode ()) & 0x7FFFFFFF;
211 for (Entry e = buckets [h % count]; e != null; e = e.next) {
212 if (e.hash == h && e.key1.Equals (a) && e.key2.Equals (b)) {
213 res = e.value;
214 return true;
217 res = null;
218 return false;
221 public void Insert (object a, object b, object value)
223 // Is it an existing one?
225 int h = (a.GetHashCode () ^ b.GetHashCode ()) & 0x7FFFFFFF;
227 for (Entry e = buckets [h % count]; e != null; e = e.next) {
228 if (e.hash == h && e.key1.Equals (a) && e.key2.Equals (b))
229 e.value = value;
232 int bucket = h % count;
233 buckets [bucket] = new Entry (a, b, h, value, buckets [bucket]);
235 // Grow whenever we double in size
236 if (size++ == count) {
237 count <<= 1;
238 count ++;
240 Entry [] newBuckets = new Entry [count];
241 foreach (Entry root in buckets) {
242 Entry e = root;
243 while (e != null) {
244 int newLoc = e.hash % count;
245 Entry n = e.next;
246 e.next = newBuckets [newLoc];
247 newBuckets [newLoc] = e;
248 e = n;
252 buckets = newBuckets;
257 class PartialMethodDefinitionInfo : MethodInfo
259 MethodOrOperator mc;
260 MethodAttributes attrs;
262 public PartialMethodDefinitionInfo (MethodOrOperator mc)
264 this.mc = mc;
265 if ((mc.ModFlags & Modifiers.STATIC) != 0)
266 attrs = MethodAttributes.Static;
269 public override MethodInfo GetBaseDefinition ()
271 throw new NotImplementedException ();
274 public override ICustomAttributeProvider ReturnTypeCustomAttributes
276 get { throw new NotImplementedException (); }
279 public override MethodAttributes Attributes
281 get { return attrs; }
284 public override MethodImplAttributes GetMethodImplementationFlags ()
286 throw new NotImplementedException ();
289 public override ParameterInfo [] GetParameters ()
291 throw new NotImplementedException ();
294 public override object Invoke (object obj, BindingFlags invokeAttr, Binder binder, object [] parameters, CultureInfo culture)
296 throw new NotImplementedException ();
299 public override RuntimeMethodHandle MethodHandle
301 get { throw new NotImplementedException (); }
304 public override Type DeclaringType
306 get { return mc.Parent.TypeBuilder; }
309 public override object [] GetCustomAttributes (Type attributeType, bool inherit)
311 throw new NotImplementedException ();
314 public override object [] GetCustomAttributes (bool inherit)
316 throw new NotImplementedException ();
319 public override Type ReturnType {
320 get {
321 return mc.MemberType;
325 public override bool IsDefined (Type attributeType, bool inherit)
327 throw new NotImplementedException ();
330 public override string Name
332 get { return mc.Name; }
335 public override Type ReflectedType
337 get { throw new NotImplementedException (); }
341 #if NET_4_0 || MS_COMPATIBLE
342 [System.Diagnostics.DebuggerDisplay ("Dynamic type")]
343 #endif
344 class DynamicType : Type
346 public override Assembly Assembly {
347 get { return CodeGen.Assembly.Builder; }
350 public override string AssemblyQualifiedName {
351 get { throw new NotImplementedException (); }
354 public override Type BaseType {
355 get { return null; }
358 public override string FullName {
359 get { return UnderlyingSystemType.FullName; }
362 public override Guid GUID {
363 get { throw new NotImplementedException (); }
366 protected override TypeAttributes GetAttributeFlagsImpl ()
368 return UnderlyingSystemType.Attributes;
371 protected override ConstructorInfo GetConstructorImpl (BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
373 throw new NotImplementedException ();
376 public override ConstructorInfo[] GetConstructors (BindingFlags bindingAttr)
378 throw new NotImplementedException ();
381 public override Type GetElementType ()
383 throw new NotImplementedException ();
386 public override EventInfo GetEvent (string name, BindingFlags bindingAttr)
388 throw new NotImplementedException ();
391 public override EventInfo[] GetEvents (BindingFlags bindingAttr)
393 throw new NotImplementedException ();
396 public override FieldInfo GetField (string name, BindingFlags bindingAttr)
398 throw new NotImplementedException ();
401 public override FieldInfo[] GetFields (BindingFlags bindingAttr)
403 throw new NotImplementedException ();
406 public override Type GetInterface (string name, bool ignoreCase)
408 throw new NotImplementedException ();
411 public override Type[] GetInterfaces ()
413 return Type.EmptyTypes;
416 public override MemberInfo[] GetMembers (BindingFlags bindingAttr)
418 throw new NotImplementedException ();
421 protected override MethodInfo GetMethodImpl (string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
423 throw new NotImplementedException ();
426 public override MethodInfo[] GetMethods (BindingFlags bindingAttr)
428 throw new NotImplementedException ();
431 public override Type GetNestedType (string name, BindingFlags bindingAttr)
433 throw new NotImplementedException ();
436 public override Type[] GetNestedTypes (BindingFlags bindingAttr)
438 throw new NotImplementedException ();
441 public override PropertyInfo[] GetProperties (BindingFlags bindingAttr)
443 throw new NotImplementedException ();
446 protected override PropertyInfo GetPropertyImpl (string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
448 throw new NotImplementedException ();
451 protected override bool HasElementTypeImpl ()
453 return false;
456 public override object InvokeMember (string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters)
458 throw new NotImplementedException ();
461 protected override bool IsArrayImpl ()
463 return false;
466 protected override bool IsByRefImpl ()
468 return false;
471 protected override bool IsCOMObjectImpl ()
473 return false;
476 protected override bool IsPointerImpl ()
478 return false;
481 protected override bool IsPrimitiveImpl ()
483 return false;
486 public override Module Module {
487 get { return UnderlyingSystemType.Module; }
490 public override string Namespace {
491 get { return UnderlyingSystemType.Namespace; }
494 public override Type UnderlyingSystemType {
495 get { return TypeManager.object_type; }
498 public override object[] GetCustomAttributes (Type attributeType, bool inherit)
500 return new object [0];
503 public override object[] GetCustomAttributes (bool inherit)
505 return new object [0];
508 public override bool IsDefined (Type attributeType, bool inherit)
510 throw new NotImplementedException ();
513 public override string Name {
514 get { return UnderlyingSystemType.Name; }
517 public override string ToString ()
519 return UnderlyingSystemType.ToString ();
522 public override RuntimeTypeHandle TypeHandle {
523 get { return UnderlyingSystemType.TypeHandle; }
526 public override Type MakeByRefType ()
528 // TODO: Wrong, hides dynamic type
529 return UnderlyingSystemType.MakeByRefType ();
533 #if NET_4_0 || MS_COMPATIBLE
534 [System.Diagnostics.DebuggerDisplay ("Dynamic array type")]
535 #endif
536 class DynamicArrayType : Type
538 readonly int rank;
539 Type reflection_type;
541 public DynamicArrayType (int rank)
543 this.rank = rank;
546 public override Assembly Assembly {
547 get { return UnderlyingSystemType.Assembly; }
550 public override string AssemblyQualifiedName {
551 get { throw new NotImplementedException (); }
554 public override Type BaseType {
555 get { return TypeManager.array_type; }
558 public override string FullName {
559 get { return UnderlyingSystemType.FullName; }
562 public override Guid GUID {
563 get { throw new NotImplementedException (); }
566 protected override TypeAttributes GetAttributeFlagsImpl ()
568 return UnderlyingSystemType.Attributes;
571 public override int GetArrayRank ()
573 return rank;
576 protected override ConstructorInfo GetConstructorImpl (BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
578 throw new NotImplementedException ();
581 public override ConstructorInfo[] GetConstructors (BindingFlags bindingAttr)
583 throw new NotImplementedException ();
586 public override Type GetElementType ()
588 return InternalType.Dynamic;
591 public override EventInfo GetEvent (string name, BindingFlags bindingAttr)
593 throw new NotImplementedException ();
596 public override EventInfo[] GetEvents (BindingFlags bindingAttr)
598 throw new NotImplementedException ();
601 public override FieldInfo GetField (string name, BindingFlags bindingAttr)
603 throw new NotImplementedException ();
606 public override FieldInfo[] GetFields (BindingFlags bindingAttr)
608 throw new NotImplementedException ();
611 public override Type GetInterface (string name, bool ignoreCase)
613 throw new NotImplementedException ();
616 public override Type[] GetInterfaces ()
618 return Type.EmptyTypes;
621 public override MemberInfo[] GetMembers (BindingFlags bindingAttr)
623 throw new NotImplementedException ();
626 protected override MethodInfo GetMethodImpl (string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
628 throw new NotImplementedException ();
631 public override MethodInfo[] GetMethods (BindingFlags bindingAttr)
633 throw new NotImplementedException ();
636 public override Type GetNestedType (string name, BindingFlags bindingAttr)
638 throw new NotImplementedException ();
641 public override Type[] GetNestedTypes (BindingFlags bindingAttr)
643 throw new NotImplementedException ();
646 public override PropertyInfo[] GetProperties (BindingFlags bindingAttr)
648 throw new NotImplementedException ();
651 protected override PropertyInfo GetPropertyImpl (string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
653 throw new NotImplementedException ();
656 protected override bool HasElementTypeImpl ()
658 return true;
661 public override object InvokeMember (string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters)
663 throw new NotImplementedException ();
666 protected override bool IsArrayImpl ()
668 return true;
671 protected override bool IsByRefImpl ()
673 return false;
676 protected override bool IsCOMObjectImpl ()
678 return false;
681 protected override bool IsPointerImpl ()
683 return false;
686 protected override bool IsPrimitiveImpl ()
688 return false;
691 public override Module Module {
692 get { return UnderlyingSystemType.Module; }
695 public override string Namespace {
696 get { return UnderlyingSystemType.Namespace; }
699 public override Type UnderlyingSystemType {
700 get {
701 if (reflection_type == null) {
702 reflection_type = rank == 1 ?
703 TypeManager.object_type.MakeArrayType () :
704 TypeManager.object_type.MakeArrayType (rank);
707 return reflection_type;
711 public override object[] GetCustomAttributes (Type attributeType, bool inherit)
713 return new object [0];
716 public override object[] GetCustomAttributes (bool inherit)
718 return new object [0];
721 public override bool IsDefined (Type attributeType, bool inherit)
723 throw new NotImplementedException ();
726 public override string Name {
727 get { return UnderlyingSystemType.Name; }
730 public override string ToString ()
732 return UnderlyingSystemType.ToString ();
735 public override RuntimeTypeHandle TypeHandle {
736 get { return UnderlyingSystemType.TypeHandle; }
740 public class UnixUtils {
741 [System.Runtime.InteropServices.DllImport ("libc", EntryPoint="isatty")]
742 extern static int _isatty (int fd);
744 public static bool isatty (int fd)
746 try {
747 return _isatty (fd) == 1;
748 } catch {
749 return false;
754 /// <summary>
755 /// An exception used to terminate the compiler resolution phase and provide completions
756 /// </summary>
757 /// <remarks>
758 /// This is thrown when we want to return the completions or
759 /// terminate the completion process by AST nodes used in
760 /// the completion process.
761 /// </remarks>
762 public class CompletionResult : Exception {
763 string [] result;
764 string base_text;
766 public CompletionResult (string base_text, string [] res)
768 if (base_text == null)
769 throw new ArgumentNullException ("base_text");
770 this.base_text = base_text;
772 result = res;
773 Array.Sort (result);
776 public string [] Result {
777 get {
778 return result;
782 public string BaseText {
783 get {
784 return base_text;