2 // support.cs: Support routines to work around the fact that System.Reflection.Emit
3 // can not introspect types that are being constructed
6 // Miguel de Icaza (miguel@ximian.com)
7 // Marek Safar (marek.safar@gmail.com)
9 // Copyright 2001 Ximian, Inc (http://www.ximian.com)
10 // Copyright 2003-2009 Novell, Inc
16 using System.Reflection;
17 using System.Reflection.Emit;
18 using System.Globalization;
19 using System.Collections.Generic;
21 namespace Mono.CSharp {
23 sealed 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 public class Tuple<T1, T2> : IEquatable<Tuple<T1, T2>>
44 public Tuple (T1 item1, T2 item2)
50 public T1 Item1 { get; private set; }
51 public T2 Item2 { get; private set; }
53 public override int GetHashCode ()
55 return Item1.GetHashCode () ^ Item2.GetHashCode ();
58 #region IEquatable<Tuple<T1,T2>> Members
60 public bool Equals (Tuple<T1, T2> other)
62 return EqualityComparer<T1>.Default.Equals (Item1, other.Item1) &&
63 EqualityComparer<T2>.Default.Equals (Item2, other.Item2);
71 public static Tuple<T1, T2> Create<T1, T2> (T1 item1, T2 item2)
73 return new Tuple<T1, T2> (item1, item2);
78 /// This is an arbitrarily seekable StreamReader wrapper.
80 /// It uses a self-tuning buffer to cache the seekable data,
81 /// but if the seek is too far, it may read the underly
82 /// stream all over from the beginning.
84 public class SeekableStreamReader : IDisposable
90 int read_ahead_length; // the length of read buffer
91 int buffer_start; // in chars
92 int char_count; // count of filled characters in buffer[]
93 int pos; // index into buffer[]
95 public SeekableStreamReader (Stream stream, Encoding encoding)
99 const int default_read_ahead = 2048;
100 InitializeStream (default_read_ahead);
101 reader = new StreamReader (stream, encoding, true);
104 public void Dispose ()
106 // Needed to release stream reader buffers
110 void InitializeStream (int read_length_inc)
112 read_ahead_length += read_length_inc;
114 int required_buffer_size = read_ahead_length * 2;
116 if (buffer == null || buffer.Length < required_buffer_size)
117 buffer = new char [required_buffer_size];
120 buffer_start = char_count = pos = 0;
124 /// This value corresponds to the current position in a stream of characters.
125 /// The StreamReader hides its manipulation of the underlying byte stream and all
126 /// character set/decoding issues. Thus, we cannot use this position to guess at
127 /// the corresponding position in the underlying byte stream even though there is
128 /// a correlation between them.
130 public int Position {
132 return buffer_start + pos;
137 // If the lookahead was too small, re-read from the beginning. Increase the buffer size while we're at it
138 // This should never happen until we are parsing some weird source code
140 if (value < buffer_start) {
141 InitializeStream (read_ahead_length);
144 // Discard buffer data after underlying stream changed position
145 // Cannot use handy reader.DiscardBufferedData () because it for
146 // some strange reason resets encoding as well
148 reader = new StreamReader (stream, reader.CurrentEncoding, true);
151 while (value > buffer_start + char_count) {
154 throw new InternalErrorException ("Seek beyond end of file: " + (buffer_start + char_count - value));
157 pos = value - buffer_start;
163 int slack = buffer.Length - char_count;
166 // read_ahead_length is only half of the buffer to deal with
167 // reads ahead and moves back without re-reading whole buffer
169 if (slack <= read_ahead_length) {
171 // shift the buffer to make room for read_ahead_length number of characters
173 int shift = read_ahead_length - slack;
174 Array.Copy (buffer, shift, buffer, 0, char_count - shift);
176 // Update all counters
179 buffer_start += shift;
183 char_count += reader.Read (buffer, char_count, slack);
185 return pos < char_count;
190 if ((pos >= char_count) && !ReadBuffer ())
198 if ((pos >= char_count) && !ReadBuffer ())
201 return buffer [pos++];
205 public class UnixUtils {
206 [System.Runtime.InteropServices.DllImport ("libc", EntryPoint="isatty")]
207 extern static int _isatty (int fd);
209 public static bool isatty (int fd)
212 return _isatty (fd) == 1;
220 /// An exception used to terminate the compiler resolution phase and provide completions
223 /// This is thrown when we want to return the completions or
224 /// terminate the completion process by AST nodes used in
225 /// the completion process.
227 public class CompletionResult : Exception {
231 public CompletionResult (string base_text, string [] res)
233 if (base_text == null)
234 throw new ArgumentNullException ("base_text");
235 this.base_text = base_text;
241 public string [] Result {
247 public string BaseText {