2009-11-23 Marek Safar <marek.safar@gmail.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 //
8 // Copyright 2001 Ximian, Inc (http://www.ximian.com)
9 // Copyright 2003-2008 Novell, Inc
10 //
11
12 using System;
13 using System.IO;
14 using System.Text;
15 using System.Reflection;
16 using System.Collections;
17 using System.Reflection.Emit;
18 using System.Globalization;
19
20 namespace Mono.CSharp {
21
22         class PtrHashtable : Hashtable {
23                 sealed class PtrComparer : IComparer, IEqualityComparer
24                 {
25                         private PtrComparer () {}
26
27                         public static PtrComparer Instance = new PtrComparer ();
28
29                         public int Compare (object x, object y)
30                         {
31                                 if (x == y)
32                                         return 0;
33                                 else
34                                         return 1;
35                         }
36
37                         bool IEqualityComparer.Equals (object x, object y)
38                         {
39                                 return x == y;
40                         }
41                         
42                         int IEqualityComparer.GetHashCode (object obj)
43                         {
44                                 return obj.GetHashCode ();
45                         }
46                 }
47
48                 public PtrHashtable () : base (PtrComparer.Instance) {}
49
50 #if MS_COMPATIBLE
51                 //
52                 // Workaround System.InvalidOperationException for enums
53                 //
54                 protected override int GetHash (object key)
55                 {
56                         TypeBuilder tb = key as TypeBuilder;
57                         if (tb != null && tb.BaseType == TypeManager.enum_type && tb.BaseType != null)
58                                 key = tb.BaseType;
59
60                         return base.GetHash (key);
61                 }
62 #endif
63         }
64
65         struct Pair {
66                 public object First;
67                 public object Second;
68
69                 public Pair (object f, object s)
70                 {
71                         First = f;
72                         Second = s;
73                 }
74         }
75
76         public class Accessors {
77                 public Accessor get_or_add;
78                 public Accessor set_or_remove;
79
80                 // was 'set' declared before 'get'?  was 'remove' declared before 'add'?
81                 public bool declared_in_reverse;
82
83                 public Accessors (Accessor get_or_add, Accessor set_or_remove)
84                 {
85                         this.get_or_add = get_or_add;
86                         this.set_or_remove = set_or_remove;
87                 }
88         }
89
90         /// <summary>
91         ///   This is an arbitrarily seekable StreamReader wrapper.
92         ///
93         ///   It uses a self-tuning buffer to cache the seekable data,
94         ///   but if the seek is too far, it may read the underly
95         ///   stream all over from the beginning.
96         /// </summary>
97         public class SeekableStreamReader
98         {
99                 const int default_average_read_length = 1024;
100                 const int buffer_read_length_spans = 3;
101
102                 TextReader reader;
103                 Stream stream;
104                 Encoding encoding;
105
106                 char[] buffer;
107                 int average_read_length;
108                 int buffer_start;       // in chars
109                 int char_count;         // count buffer[] valid characters
110                 int pos;                // index into buffer[]
111
112                 void ResetStream (int read_length_inc)
113                 {
114                         average_read_length += read_length_inc;
115                         stream.Position = 0;
116                         reader = new StreamReader (stream, encoding, true);
117                         buffer = new char [average_read_length * buffer_read_length_spans];
118                         buffer_start = char_count = pos = 0;
119                 }
120
121                 public SeekableStreamReader (Stream stream, Encoding encoding)
122                 {
123                         this.stream = stream;
124                         this.encoding = encoding;
125
126                         ResetStream (default_average_read_length);
127                 }
128
129                 /// <remarks>
130                 ///   This value corresponds to the current position in a stream of characters.
131                 ///   The StreamReader hides its manipulation of the underlying byte stream and all
132                 ///   character set/decoding issues.  Thus, we cannot use this position to guess at
133                 ///   the corresponding position in the underlying byte stream even though there is
134                 ///   a correlation between them.
135                 /// </remarks>
136                 public int Position {
137                         get { return buffer_start + pos; }
138
139                         set {
140                                 // If the lookahead was too small, re-read from the beginning.  Increase the buffer size while we're at it
141                                 if (value < buffer_start)
142                                         ResetStream (average_read_length / 2);
143
144                                 while (value > buffer_start + char_count) {
145                                         pos = char_count;
146                                         if (!ReadBuffer ())
147                                                 throw new InternalErrorException ("Seek beyond end of file: " + (buffer_start + char_count - value));
148                                 }
149
150                                 pos = value - buffer_start;
151                         }
152                 }
153
154                 private bool ReadBuffer ()
155                 {
156                         int slack = buffer.Length - char_count;
157                         if (slack <= average_read_length / 2) {
158                                 // shift the buffer to make room for average_read_length number of characters
159                                 int shift = average_read_length - slack;
160                                 Array.Copy (buffer, shift, buffer, 0, char_count - shift);
161                                 pos -= shift;
162                                 char_count -= shift;
163                                 buffer_start += shift;
164                                 slack += shift;         // slack == average_read_length
165                         }
166
167                         char_count += reader.Read (buffer, char_count, slack);
168
169                         return pos < char_count;
170                 }
171
172                 public int Peek ()
173                 {
174                         if ((pos >= char_count) && !ReadBuffer ())
175                                 return -1;
176
177                         return buffer [pos];
178                 }
179
180                 public int Read ()
181                 {
182                         if ((pos >= char_count) && !ReadBuffer ())
183                                 return -1;
184
185                         return buffer [pos++];
186                 }
187         }
188
189         public class DoubleHash {
190                 const int DEFAULT_INITIAL_BUCKETS = 100;
191
192                 public DoubleHash () : this (DEFAULT_INITIAL_BUCKETS) {}
193
194                 public DoubleHash (int size)
195                 {
196                         count = size;
197                         buckets = new Entry [size];
198                 }
199
200                 int count;
201                 Entry [] buckets;
202                 int size = 0;
203
204                 class Entry {
205                         public object key1;
206                         public object key2;
207                         public int hash;
208                         public object value;
209                         public Entry next;
210
211                         public Entry (object key1, object key2, int hash, object value, Entry next)
212                         {
213                                 this.key1 = key1;
214                                 this.key2 = key2;
215                                 this.hash = hash;
216                                 this.next = next;
217                                 this.value = value;
218                         }
219                 }
220
221                 public bool Lookup (object a, object b, out object res)
222                 {
223                         int h = (a.GetHashCode () ^ b.GetHashCode ()) & 0x7FFFFFFF;
224
225                         for (Entry e = buckets [h % count]; e != null; e = e.next) {
226                                 if (e.hash == h && e.key1.Equals (a) && e.key2.Equals (b)) {
227                                         res = e.value;
228                                         return true;
229                                 }
230                         }
231                         res = null;
232                         return false;
233                 }
234
235                 public void Insert (object a, object b, object value)
236                 {
237                         // Is it an existing one?
238
239                         int h = (a.GetHashCode () ^ b.GetHashCode ()) & 0x7FFFFFFF;
240
241                         for (Entry e = buckets [h % count]; e != null; e = e.next) {
242                                 if (e.hash == h && e.key1.Equals (a) && e.key2.Equals (b))
243                                         e.value = value;
244                         }
245
246                         int bucket = h % count;
247                         buckets [bucket] = new Entry (a, b, h, value, buckets [bucket]);
248
249                         // Grow whenever we double in size
250                         if (size++ == count) {
251                                 count <<= 1;
252                                 count ++;
253
254                                 Entry [] newBuckets = new Entry [count];
255                                 foreach (Entry root in buckets) {
256                                         Entry e = root;
257                                         while (e != null) {
258                                                 int newLoc = e.hash % count;
259                                                 Entry n = e.next;
260                                                 e.next = newBuckets [newLoc];
261                                                 newBuckets [newLoc] = e;
262                                                 e = n;
263                                         }
264                                 }
265
266                                 buckets = newBuckets;
267                         }
268                 }
269         }
270
271         class PartialMethodDefinitionInfo : MethodInfo
272         {
273                 MethodOrOperator mc;
274                 MethodAttributes attrs;
275
276                 public PartialMethodDefinitionInfo (MethodOrOperator mc)
277                 {
278                         this.mc = mc;
279                         if ((mc.ModFlags & Modifiers.STATIC) != 0)
280                                 attrs = MethodAttributes.Static;
281                 }
282
283                 public override MethodInfo GetBaseDefinition ()
284                 {
285                         throw new NotImplementedException ();
286                 }
287
288                 public override ICustomAttributeProvider ReturnTypeCustomAttributes
289                 {
290                         get { throw new NotImplementedException (); }
291                 }
292
293                 public override MethodAttributes Attributes
294                 {
295                         get { return attrs; }
296                 }
297
298                 public override MethodImplAttributes GetMethodImplementationFlags ()
299                 {
300                         throw new NotImplementedException ();
301                 }
302
303                 public override ParameterInfo [] GetParameters ()
304                 {
305                         throw new NotImplementedException ();
306                 }
307
308                 public override object Invoke (object obj, BindingFlags invokeAttr, Binder binder, object [] parameters, CultureInfo culture)
309                 {
310                         throw new NotImplementedException ();
311                 }
312
313                 public override RuntimeMethodHandle MethodHandle
314                 {
315                         get { throw new NotImplementedException (); }
316                 }
317
318                 public override Type DeclaringType
319                 {
320                         get { return mc.Parent.TypeBuilder; }
321                 }
322
323                 public override object [] GetCustomAttributes (Type attributeType, bool inherit)
324                 {
325                         throw new NotImplementedException ();
326                 }
327
328                 public override object [] GetCustomAttributes (bool inherit)
329                 {
330                         throw new NotImplementedException ();
331                 }
332
333                 public override Type ReturnType {
334                         get {
335                                 return mc.MemberType;
336                         }
337                 }
338
339                 public override bool IsDefined (Type attributeType, bool inherit)
340                 {
341                         throw new NotImplementedException ();
342                 }
343
344                 public override string Name
345                 {
346                         get { return mc.Name; }
347                 }
348
349                 public override Type ReflectedType
350                 {
351                         get { throw new NotImplementedException (); }
352                 }
353         }
354
355 #if NET_4_0 || MS_COMPATIBLE
356         [System.Diagnostics.DebuggerDisplay ("Dynamic type")]
357 #endif
358         class DynamicType : Type
359         {
360                 public override Assembly Assembly {
361                         get { return UnderlyingSystemType.Assembly; }
362                 }
363
364                 public override string AssemblyQualifiedName {
365                         get { throw new NotImplementedException (); }
366                 }
367
368                 public override Type BaseType {
369                         get { return null; }
370                 }
371
372                 public override string FullName {
373                         get { return UnderlyingSystemType.FullName; }
374                 }
375
376                 public override Guid GUID {
377                         get { throw new NotImplementedException (); }
378                 }
379
380                 protected override TypeAttributes GetAttributeFlagsImpl ()
381                 {
382                         return UnderlyingSystemType.Attributes;
383                 }
384
385                 protected override ConstructorInfo GetConstructorImpl (BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
386                 {
387                         throw new NotImplementedException ();
388                 }
389
390                 public override ConstructorInfo[] GetConstructors (BindingFlags bindingAttr)
391                 {
392                         throw new NotImplementedException ();
393                 }
394
395                 public override Type GetElementType ()
396                 {
397                         throw new NotImplementedException ();
398                 }
399
400                 public override EventInfo GetEvent (string name, BindingFlags bindingAttr)
401                 {
402                         throw new NotImplementedException ();
403                 }
404
405                 public override EventInfo[] GetEvents (BindingFlags bindingAttr)
406                 {
407                         throw new NotImplementedException ();
408                 }
409
410                 public override FieldInfo GetField (string name, BindingFlags bindingAttr)
411                 {
412                         throw new NotImplementedException ();
413                 }
414
415                 public override FieldInfo[] GetFields (BindingFlags bindingAttr)
416                 {
417                         throw new NotImplementedException ();
418                 }
419
420                 public override Type GetInterface (string name, bool ignoreCase)
421                 {
422                         throw new NotImplementedException ();
423                 }
424
425                 public override Type[] GetInterfaces ()
426                 {
427                         return Type.EmptyTypes;
428                 }
429
430                 public override MemberInfo[] GetMembers (BindingFlags bindingAttr)
431                 {
432                         throw new NotImplementedException ();
433                 }
434
435                 protected override MethodInfo GetMethodImpl (string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
436                 {
437                         throw new NotImplementedException ();
438                 }
439
440                 public override MethodInfo[] GetMethods (BindingFlags bindingAttr)
441                 {
442                         throw new NotImplementedException ();
443                 }
444
445                 public override Type GetNestedType (string name, BindingFlags bindingAttr)
446                 {
447                         throw new NotImplementedException ();
448                 }
449
450                 public override Type[] GetNestedTypes (BindingFlags bindingAttr)
451                 {
452                         throw new NotImplementedException ();
453                 }
454
455                 public override PropertyInfo[] GetProperties (BindingFlags bindingAttr)
456                 {
457                         throw new NotImplementedException ();
458                 }
459
460                 protected override PropertyInfo GetPropertyImpl (string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
461                 {
462                         throw new NotImplementedException ();
463                 }
464
465                 protected override bool HasElementTypeImpl ()
466                 {
467                         return false;
468                 }
469
470                 public override object InvokeMember (string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters)
471                 {
472                         throw new NotImplementedException ();
473                 }
474
475                 protected override bool IsArrayImpl ()
476                 {
477                         return false;
478                 }
479
480                 protected override bool IsByRefImpl ()
481                 {
482                         return false;
483                 }
484
485                 protected override bool IsCOMObjectImpl ()
486                 {
487                         return false;
488                 }
489
490                 protected override bool IsPointerImpl ()
491                 {
492                         return false;
493                 }
494
495                 protected override bool IsPrimitiveImpl ()
496                 {
497                         return false;
498                 }
499
500                 public override Module Module {
501                         get { return UnderlyingSystemType.Module; }
502                 }
503
504                 public override string Namespace {
505                         get { return UnderlyingSystemType.Namespace; }
506                 }
507
508                 public override Type UnderlyingSystemType {
509                         get { return TypeManager.object_type; }
510                 }
511
512                 public override object[] GetCustomAttributes (Type attributeType, bool inherit)
513                 {
514                         return new object [0];
515                 }
516
517                 public override object[] GetCustomAttributes (bool inherit)
518                 {
519                         return new object [0];
520                 }
521
522                 public override bool IsDefined (Type attributeType, bool inherit)
523                 {
524                         throw new NotImplementedException ();
525                 }
526
527                 public override string Name {
528                         get { return UnderlyingSystemType.Name; }
529                 }
530
531                 public override string ToString ()
532                 {
533                         return UnderlyingSystemType.ToString ();
534                 }
535
536                 public override RuntimeTypeHandle TypeHandle {
537                         get { return UnderlyingSystemType.TypeHandle; }
538                 }
539
540                 public override Type MakeByRefType ()
541                 {
542                         // TODO: Wrong, hides dynamic type
543                         return UnderlyingSystemType.MakeByRefType ();
544                 }
545         }
546
547 #if NET_4_0 || MS_COMPATIBLE
548         [System.Diagnostics.DebuggerDisplay ("Dynamic array type")]
549 #endif
550         class DynamicArrayType : Type
551         {
552                 readonly int rank;
553                 Type reflection_type;
554
555                 public DynamicArrayType (int rank)
556                 {
557                         this.rank = rank;
558                 }
559
560                 public override Assembly Assembly {
561                         get { return UnderlyingSystemType.Assembly; }
562                 }
563
564                 public override string AssemblyQualifiedName {
565                         get { throw new NotImplementedException (); }
566                 }
567
568                 public override Type BaseType {
569                         get { return TypeManager.array_type; }
570                 }
571
572                 public override string FullName {
573                         get { return UnderlyingSystemType.FullName; }
574                 }
575
576                 public override Guid GUID {
577                         get { throw new NotImplementedException (); }
578                 }
579
580                 protected override TypeAttributes GetAttributeFlagsImpl ()
581                 {
582                         return UnderlyingSystemType.Attributes;
583                 }
584
585                 public override int GetArrayRank ()
586                 {
587                         return rank;
588                 }
589
590                 protected override ConstructorInfo GetConstructorImpl (BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
591                 {
592                         throw new NotImplementedException ();
593                 }
594
595                 public override ConstructorInfo[] GetConstructors (BindingFlags bindingAttr)
596                 {
597                         throw new NotImplementedException ();
598                 }
599
600                 public override Type GetElementType ()
601                 {
602                         return InternalType.Dynamic;
603                 }
604
605                 public override EventInfo GetEvent (string name, BindingFlags bindingAttr)
606                 {
607                         throw new NotImplementedException ();
608                 }
609
610                 public override EventInfo[] GetEvents (BindingFlags bindingAttr)
611                 {
612                         throw new NotImplementedException ();
613                 }
614
615                 public override FieldInfo GetField (string name, BindingFlags bindingAttr)
616                 {
617                         throw new NotImplementedException ();
618                 }
619
620                 public override FieldInfo[] GetFields (BindingFlags bindingAttr)
621                 {
622                         throw new NotImplementedException ();
623                 }
624
625                 public override Type GetInterface (string name, bool ignoreCase)
626                 {
627                         throw new NotImplementedException ();
628                 }
629
630                 public override Type[] GetInterfaces ()
631                 {
632                         return Type.EmptyTypes;
633                 }
634
635                 public override MemberInfo[] GetMembers (BindingFlags bindingAttr)
636                 {
637                         throw new NotImplementedException ();
638                 }
639
640                 protected override MethodInfo GetMethodImpl (string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
641                 {
642                         throw new NotImplementedException ();
643                 }
644
645                 public override MethodInfo[] GetMethods (BindingFlags bindingAttr)
646                 {
647                         throw new NotImplementedException ();
648                 }
649
650                 public override Type GetNestedType (string name, BindingFlags bindingAttr)
651                 {
652                         throw new NotImplementedException ();
653                 }
654
655                 public override Type[] GetNestedTypes (BindingFlags bindingAttr)
656                 {
657                         throw new NotImplementedException ();
658                 }
659
660                 public override PropertyInfo[] GetProperties (BindingFlags bindingAttr)
661                 {
662                         throw new NotImplementedException ();
663                 }
664
665                 protected override PropertyInfo GetPropertyImpl (string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
666                 {
667                         throw new NotImplementedException ();
668                 }
669
670                 protected override bool HasElementTypeImpl ()
671                 {
672                         return true;
673                 }
674
675                 public override object InvokeMember (string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters)
676                 {
677                         throw new NotImplementedException ();
678                 }
679
680                 protected override bool IsArrayImpl ()
681                 {
682                         return true;
683                 }
684
685                 protected override bool IsByRefImpl ()
686                 {
687                         return false;
688                 }
689
690                 protected override bool IsCOMObjectImpl ()
691                 {
692                         return false;
693                 }
694
695                 protected override bool IsPointerImpl ()
696                 {
697                         return false;
698                 }
699
700                 protected override bool IsPrimitiveImpl ()
701                 {
702                         return false;
703                 }
704
705                 public override Module Module {
706                         get { return UnderlyingSystemType.Module; }
707                 }
708
709                 public override string Namespace {
710                         get { return UnderlyingSystemType.Namespace; }
711                 }
712
713                 public override Type UnderlyingSystemType {
714                         get {
715                                 if (reflection_type == null) {
716                                         reflection_type = rank == 1 ?
717                                                 TypeManager.object_type.MakeArrayType () :
718                                                 TypeManager.object_type.MakeArrayType (rank);
719                                 }
720
721                                 return reflection_type;
722                         }
723                 }
724
725                 public override object[] GetCustomAttributes (Type attributeType, bool inherit)
726                 {
727                         return new object [0];
728                 }
729
730                 public override object[] GetCustomAttributes (bool inherit)
731                 {
732                         return new object [0];
733                 }
734
735                 public override bool IsDefined (Type attributeType, bool inherit)
736                 {
737                         throw new NotImplementedException ();
738                 }
739
740                 public override string Name {
741                         get { return UnderlyingSystemType.Name; }
742                 }
743
744                 public override string ToString ()
745                 {
746                         return UnderlyingSystemType.ToString ();
747                 }
748
749                 public override RuntimeTypeHandle TypeHandle {
750                         get { return UnderlyingSystemType.TypeHandle; }
751                 }
752         }
753
754         public class UnixUtils {
755                 [System.Runtime.InteropServices.DllImport ("libc", EntryPoint="isatty")]
756                 extern static int _isatty (int fd);
757                         
758                 public static bool isatty (int fd)
759                 {
760                         try {
761                                 return _isatty (fd) == 1;
762                         } catch {
763                                 return false;
764                         }
765                 }
766         }
767
768         /// <summary>
769         ///   An exception used to terminate the compiler resolution phase and provide completions
770         /// </summary>
771         /// <remarks>
772         ///   This is thrown when we want to return the completions or
773         ///   terminate the completion process by AST nodes used in
774         ///   the completion process.
775         /// </remarks>
776         public class CompletionResult : Exception {
777                 string [] result;
778                 string base_text;
779                 
780                 public CompletionResult (string base_text, string [] res)
781                 {
782                         if (base_text == null)
783                                 throw new ArgumentNullException ("base_text");
784                         this.base_text = base_text;
785
786                         result = res;
787                         Array.Sort (result);
788                 }
789
790                 public string [] Result {
791                         get {
792                                 return result;
793                         }
794                 }
795
796                 public string BaseText {
797                         get {
798                                 return base_text;
799                         }
800                 }
801         }
802 }