2009-12-14 Rodrigo Kumpera <rkumpera@novell.com>
[mono.git] / mcs / mcs / support.cs
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
11 //
12
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;
20
21 namespace Mono.CSharp {
22
23         class ReferenceEquality<T> : IEqualityComparer<T> where T : class
24         {
25                 public static readonly IEqualityComparer<T> Default = new ReferenceEquality<T> ();
26
27                 private ReferenceEquality ()
28                 {
29                 }
30
31                 public bool Equals (T x, T y)
32                 {
33                         return object.ReferenceEquals (x, y);
34                 }
35
36                 public int GetHashCode (T obj)
37                 {
38                         return obj == null ? 0 : obj.GetHashCode ();
39                 }
40         }
41
42         class Tuple<T1, T2>
43         {
44                 public Tuple (T1 item1, T2 item2)
45                 {
46                         Item1 = item1;
47                         Item2 = item2;
48                 }
49
50                 public T1 Item1 { get; private set; }
51                 public T2 Item2 { get; private set; }
52         }
53
54         public class Accessors {
55                 public Accessor get_or_add;
56                 public Accessor set_or_remove;
57
58                 // was 'set' declared before 'get'?  was 'remove' declared before 'add'?
59                 public bool declared_in_reverse;
60
61                 public Accessors (Accessor get_or_add, Accessor set_or_remove)
62                 {
63                         this.get_or_add = get_or_add;
64                         this.set_or_remove = set_or_remove;
65                 }
66         }
67
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
76         {
77                 const int buffer_read_length_spans = 3;
78
79                 TextReader reader;
80                 Stream stream;
81
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[]
87
88                 public SeekableStreamReader (Stream stream, Encoding encoding)
89                 {
90                         this.stream = stream;
91
92                         const int default_average_read_length = 1024;
93                         InitializeStream (default_average_read_length);
94                         reader = new StreamReader (stream, encoding, true);
95                 }
96
97                 public void Dispose ()
98                 {
99                         // Needed to release stream reader buffers
100                         reader.Dispose ();
101                 }
102
103                 void InitializeStream (int read_length_inc)
104                 {
105                         average_read_length += read_length_inc;
106
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];
110
111                         stream.Position = 0;                    
112                         buffer_start = char_count = pos = 0;
113                 }
114
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; }
124
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);
129
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));
134                                 }
135
136                                 pos = value - buffer_start;
137                         }
138                 }
139
140                 private bool ReadBuffer ()
141                 {
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
151                         }
152
153                         char_count += reader.Read (buffer, char_count, slack);
154
155                         return pos < char_count;
156                 }
157
158                 public int Peek ()
159                 {
160                         if ((pos >= char_count) && !ReadBuffer ())
161                                 return -1;
162
163                         return buffer [pos];
164                 }
165
166                 public int Read ()
167                 {
168                         if ((pos >= char_count) && !ReadBuffer ())
169                                 return -1;
170
171                         return buffer [pos++];
172                 }
173         }
174
175         public class DoubleHash {
176                 const int DEFAULT_INITIAL_BUCKETS = 100;
177
178                 public DoubleHash () : this (DEFAULT_INITIAL_BUCKETS) {}
179
180                 public DoubleHash (int size)
181                 {
182                         count = size;
183                         buckets = new Entry [size];
184                 }
185
186                 int count;
187                 Entry [] buckets;
188                 int size = 0;
189
190                 class Entry {
191                         public object key1;
192                         public object key2;
193                         public int hash;
194                         public object value;
195                         public Entry next;
196
197                         public Entry (object key1, object key2, int hash, object value, Entry next)
198                         {
199                                 this.key1 = key1;
200                                 this.key2 = key2;
201                                 this.hash = hash;
202                                 this.next = next;
203                                 this.value = value;
204                         }
205                 }
206
207                 public bool Lookup (object a, object b, out object res)
208                 {
209                         int h = (a.GetHashCode () ^ b.GetHashCode ()) & 0x7FFFFFFF;
210
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;
215                                 }
216                         }
217                         res = null;
218                         return false;
219                 }
220
221                 public void Insert (object a, object b, object value)
222                 {
223                         // Is it an existing one?
224
225                         int h = (a.GetHashCode () ^ b.GetHashCode ()) & 0x7FFFFFFF;
226
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;
230                         }
231
232                         int bucket = h % count;
233                         buckets [bucket] = new Entry (a, b, h, value, buckets [bucket]);
234
235                         // Grow whenever we double in size
236                         if (size++ == count) {
237                                 count <<= 1;
238                                 count ++;
239
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;
249                                         }
250                                 }
251
252                                 buckets = newBuckets;
253                         }
254                 }
255         }
256
257         class PartialMethodDefinitionInfo : MethodInfo
258         {
259                 MethodOrOperator mc;
260                 MethodAttributes attrs;
261
262                 public PartialMethodDefinitionInfo (MethodOrOperator mc)
263                 {
264                         this.mc = mc;
265                         if ((mc.ModFlags & Modifiers.STATIC) != 0)
266                                 attrs = MethodAttributes.Static;
267                 }
268
269                 public override MethodInfo GetBaseDefinition ()
270                 {
271                         throw new NotImplementedException ();
272                 }
273
274                 public override ICustomAttributeProvider ReturnTypeCustomAttributes
275                 {
276                         get { throw new NotImplementedException (); }
277                 }
278
279                 public override MethodAttributes Attributes
280                 {
281                         get { return attrs; }
282                 }
283
284                 public override MethodImplAttributes GetMethodImplementationFlags ()
285                 {
286                         throw new NotImplementedException ();
287                 }
288
289                 public override ParameterInfo [] GetParameters ()
290                 {
291                         throw new NotImplementedException ();
292                 }
293
294                 public override object Invoke (object obj, BindingFlags invokeAttr, Binder binder, object [] parameters, CultureInfo culture)
295                 {
296                         throw new NotImplementedException ();
297                 }
298
299                 public override RuntimeMethodHandle MethodHandle
300                 {
301                         get { throw new NotImplementedException (); }
302                 }
303
304                 public override Type DeclaringType
305                 {
306                         get { return mc.Parent.TypeBuilder; }
307                 }
308
309                 public override object [] GetCustomAttributes (Type attributeType, bool inherit)
310                 {
311                         throw new NotImplementedException ();
312                 }
313
314                 public override object [] GetCustomAttributes (bool inherit)
315                 {
316                         throw new NotImplementedException ();
317                 }
318
319                 public override Type ReturnType {
320                         get {
321                                 return mc.MemberType;
322                         }
323                 }
324
325                 public override bool IsDefined (Type attributeType, bool inherit)
326                 {
327                         throw new NotImplementedException ();
328                 }
329
330                 public override string Name
331                 {
332                         get { return mc.Name; }
333                 }
334
335                 public override Type ReflectedType
336                 {
337                         get { throw new NotImplementedException (); }
338                 }
339         }
340
341 #if NET_4_0 || MS_COMPATIBLE
342         [System.Diagnostics.DebuggerDisplay ("Dynamic type")]
343 #endif
344         class DynamicType : Type
345         {
346                 public override Assembly Assembly {
347                         get { return CodeGen.Assembly.Builder; }
348                 }
349
350                 public override string AssemblyQualifiedName {
351                         get { throw new NotImplementedException (); }
352                 }
353
354                 public override Type BaseType {
355                         get { return null; }
356                 }
357
358                 public override string FullName {
359                         get { return UnderlyingSystemType.FullName; }
360                 }
361
362                 public override Guid GUID {
363                         get { throw new NotImplementedException (); }
364                 }
365
366                 protected override TypeAttributes GetAttributeFlagsImpl ()
367                 {
368                         return UnderlyingSystemType.Attributes;
369                 }
370
371                 protected override ConstructorInfo GetConstructorImpl (BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
372                 {
373                         throw new NotImplementedException ();
374                 }
375
376                 public override ConstructorInfo[] GetConstructors (BindingFlags bindingAttr)
377                 {
378                         throw new NotImplementedException ();
379                 }
380
381                 public override Type GetElementType ()
382                 {
383                         throw new NotImplementedException ();
384                 }
385
386                 public override EventInfo GetEvent (string name, BindingFlags bindingAttr)
387                 {
388                         throw new NotImplementedException ();
389                 }
390
391                 public override EventInfo[] GetEvents (BindingFlags bindingAttr)
392                 {
393                         throw new NotImplementedException ();
394                 }
395
396                 public override FieldInfo GetField (string name, BindingFlags bindingAttr)
397                 {
398                         throw new NotImplementedException ();
399                 }
400
401                 public override FieldInfo[] GetFields (BindingFlags bindingAttr)
402                 {
403                         throw new NotImplementedException ();
404                 }
405
406                 public override Type GetInterface (string name, bool ignoreCase)
407                 {
408                         throw new NotImplementedException ();
409                 }
410
411                 public override Type[] GetInterfaces ()
412                 {
413                         return Type.EmptyTypes;
414                 }
415
416                 public override MemberInfo[] GetMembers (BindingFlags bindingAttr)
417                 {
418                         throw new NotImplementedException ();
419                 }
420
421                 protected override MethodInfo GetMethodImpl (string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
422                 {
423                         throw new NotImplementedException ();
424                 }
425
426                 public override MethodInfo[] GetMethods (BindingFlags bindingAttr)
427                 {
428                         throw new NotImplementedException ();
429                 }
430
431                 public override Type GetNestedType (string name, BindingFlags bindingAttr)
432                 {
433                         throw new NotImplementedException ();
434                 }
435
436                 public override Type[] GetNestedTypes (BindingFlags bindingAttr)
437                 {
438                         throw new NotImplementedException ();
439                 }
440
441                 public override PropertyInfo[] GetProperties (BindingFlags bindingAttr)
442                 {
443                         throw new NotImplementedException ();
444                 }
445
446                 protected override PropertyInfo GetPropertyImpl (string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
447                 {
448                         throw new NotImplementedException ();
449                 }
450
451                 protected override bool HasElementTypeImpl ()
452                 {
453                         return false;
454                 }
455
456                 public override object InvokeMember (string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters)
457                 {
458                         throw new NotImplementedException ();
459                 }
460
461                 protected override bool IsArrayImpl ()
462                 {
463                         return false;
464                 }
465
466                 protected override bool IsByRefImpl ()
467                 {
468                         return false;
469                 }
470
471                 protected override bool IsCOMObjectImpl ()
472                 {
473                         return false;
474                 }
475
476                 protected override bool IsPointerImpl ()
477                 {
478                         return false;
479                 }
480
481                 protected override bool IsPrimitiveImpl ()
482                 {
483                         return false;
484                 }
485
486                 public override Module Module {
487                         get { return UnderlyingSystemType.Module; }
488                 }
489
490                 public override string Namespace {
491                         get { return UnderlyingSystemType.Namespace; }
492                 }
493
494                 public override Type UnderlyingSystemType {
495                         get { return TypeManager.object_type; }
496                 }
497
498                 public override object[] GetCustomAttributes (Type attributeType, bool inherit)
499                 {
500                         return new object [0];
501                 }
502
503                 public override object[] GetCustomAttributes (bool inherit)
504                 {
505                         return new object [0];
506                 }
507
508                 public override bool IsDefined (Type attributeType, bool inherit)
509                 {
510                         throw new NotImplementedException ();
511                 }
512
513                 public override string Name {
514                         get { return UnderlyingSystemType.Name; }
515                 }
516
517                 public override string ToString ()
518                 {
519                         return UnderlyingSystemType.ToString ();
520                 }
521
522                 public override RuntimeTypeHandle TypeHandle {
523                         get { return UnderlyingSystemType.TypeHandle; }
524                 }
525
526                 public override Type MakeByRefType ()
527                 {
528                         // TODO: Wrong, hides dynamic type
529                         return UnderlyingSystemType.MakeByRefType ();
530                 }
531         }
532
533 #if NET_4_0 || MS_COMPATIBLE
534         [System.Diagnostics.DebuggerDisplay ("Dynamic array type")]
535 #endif
536         class DynamicArrayType : Type
537         {
538                 readonly int rank;
539                 Type reflection_type;
540
541                 public DynamicArrayType (int rank)
542                 {
543                         this.rank = rank;
544                 }
545
546                 public override Assembly Assembly {
547                         get { return UnderlyingSystemType.Assembly; }
548                 }
549
550                 public override string AssemblyQualifiedName {
551                         get { throw new NotImplementedException (); }
552                 }
553
554                 public override Type BaseType {
555                         get { return TypeManager.array_type; }
556                 }
557
558                 public override string FullName {
559                         get { return UnderlyingSystemType.FullName; }
560                 }
561
562                 public override Guid GUID {
563                         get { throw new NotImplementedException (); }
564                 }
565
566                 protected override TypeAttributes GetAttributeFlagsImpl ()
567                 {
568                         return UnderlyingSystemType.Attributes;
569                 }
570
571                 public override int GetArrayRank ()
572                 {
573                         return rank;
574                 }
575
576                 protected override ConstructorInfo GetConstructorImpl (BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
577                 {
578                         throw new NotImplementedException ();
579                 }
580
581                 public override ConstructorInfo[] GetConstructors (BindingFlags bindingAttr)
582                 {
583                         throw new NotImplementedException ();
584                 }
585
586                 public override Type GetElementType ()
587                 {
588                         return InternalType.Dynamic;
589                 }
590
591                 public override EventInfo GetEvent (string name, BindingFlags bindingAttr)
592                 {
593                         throw new NotImplementedException ();
594                 }
595
596                 public override EventInfo[] GetEvents (BindingFlags bindingAttr)
597                 {
598                         throw new NotImplementedException ();
599                 }
600
601                 public override FieldInfo GetField (string name, BindingFlags bindingAttr)
602                 {
603                         throw new NotImplementedException ();
604                 }
605
606                 public override FieldInfo[] GetFields (BindingFlags bindingAttr)
607                 {
608                         throw new NotImplementedException ();
609                 }
610
611                 public override Type GetInterface (string name, bool ignoreCase)
612                 {
613                         throw new NotImplementedException ();
614                 }
615
616                 public override Type[] GetInterfaces ()
617                 {
618                         return Type.EmptyTypes;
619                 }
620
621                 public override MemberInfo[] GetMembers (BindingFlags bindingAttr)
622                 {
623                         throw new NotImplementedException ();
624                 }
625
626                 protected override MethodInfo GetMethodImpl (string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
627                 {
628                         throw new NotImplementedException ();
629                 }
630
631                 public override MethodInfo[] GetMethods (BindingFlags bindingAttr)
632                 {
633                         throw new NotImplementedException ();
634                 }
635
636                 public override Type GetNestedType (string name, BindingFlags bindingAttr)
637                 {
638                         throw new NotImplementedException ();
639                 }
640
641                 public override Type[] GetNestedTypes (BindingFlags bindingAttr)
642                 {
643                         throw new NotImplementedException ();
644                 }
645
646                 public override PropertyInfo[] GetProperties (BindingFlags bindingAttr)
647                 {
648                         throw new NotImplementedException ();
649                 }
650
651                 protected override PropertyInfo GetPropertyImpl (string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
652                 {
653                         throw new NotImplementedException ();
654                 }
655
656                 protected override bool HasElementTypeImpl ()
657                 {
658                         return true;
659                 }
660
661                 public override object InvokeMember (string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters)
662                 {
663                         throw new NotImplementedException ();
664                 }
665
666                 protected override bool IsArrayImpl ()
667                 {
668                         return true;
669                 }
670
671                 protected override bool IsByRefImpl ()
672                 {
673                         return false;
674                 }
675
676                 protected override bool IsCOMObjectImpl ()
677                 {
678                         return false;
679                 }
680
681                 protected override bool IsPointerImpl ()
682                 {
683                         return false;
684                 }
685
686                 protected override bool IsPrimitiveImpl ()
687                 {
688                         return false;
689                 }
690
691                 public override Module Module {
692                         get { return UnderlyingSystemType.Module; }
693                 }
694
695                 public override string Namespace {
696                         get { return UnderlyingSystemType.Namespace; }
697                 }
698
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);
705                                 }
706
707                                 return reflection_type;
708                         }
709                 }
710
711                 public override object[] GetCustomAttributes (Type attributeType, bool inherit)
712                 {
713                         return new object [0];
714                 }
715
716                 public override object[] GetCustomAttributes (bool inherit)
717                 {
718                         return new object [0];
719                 }
720
721                 public override bool IsDefined (Type attributeType, bool inherit)
722                 {
723                         throw new NotImplementedException ();
724                 }
725
726                 public override string Name {
727                         get { return UnderlyingSystemType.Name; }
728                 }
729
730                 public override string ToString ()
731                 {
732                         return UnderlyingSystemType.ToString ();
733                 }
734
735                 public override RuntimeTypeHandle TypeHandle {
736                         get { return UnderlyingSystemType.TypeHandle; }
737                 }
738         }
739
740         public class UnixUtils {
741                 [System.Runtime.InteropServices.DllImport ("libc", EntryPoint="isatty")]
742                 extern static int _isatty (int fd);
743                         
744                 public static bool isatty (int fd)
745                 {
746                         try {
747                                 return _isatty (fd) == 1;
748                         } catch {
749                                 return false;
750                         }
751                 }
752         }
753
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;
765                 
766                 public CompletionResult (string base_text, string [] res)
767                 {
768                         if (base_text == null)
769                                 throw new ArgumentNullException ("base_text");
770                         this.base_text = base_text;
771
772                         result = res;
773                         Array.Sort (result);
774                 }
775
776                 public string [] Result {
777                         get {
778                                 return result;
779                         }
780                 }
781
782                 public string BaseText {
783                         get {
784                                 return base_text;
785                         }
786                 }
787         }
788 }