Free cookie consent management tool by TermsFeed Policy Generator

source: tags/3.3.11/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory-5.5.0/Semantics/Conversion.cs @ 13398

Last change on this file since 13398 was 11700, checked in by jkarder, 9 years ago

#2077: created branch and added first version

File size: 16.9 KB
Line 
1// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4// software and associated documentation files (the "Software"), to deal in the Software
5// without restriction, including without limitation the rights to use, copy, modify, merge,
6// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7// to whom the Software is furnished to do so, subject to the following conditions:
8//
9// The above copyright notice and this permission notice shall be included in all copies or
10// substantial portions of the Software.
11//
12// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17// DEALINGS IN THE SOFTWARE.
18
19using System;
20using ICSharpCode.NRefactory.TypeSystem;
21
22namespace ICSharpCode.NRefactory.Semantics
23{
24  /// <summary>
25  /// Holds information about a conversion between two types.
26  /// </summary>
27  public abstract class Conversion : IEquatable<Conversion>
28  {
29    #region Conversion factory methods
30    /// <summary>
31    /// Not a valid conversion.
32    /// </summary>
33    public static readonly Conversion None = new InvalidConversion();
34   
35    /// <summary>
36    /// Identity conversion.
37    /// </summary>
38    public static readonly Conversion IdentityConversion = new BuiltinConversion(true, 0);
39   
40    public static readonly Conversion ImplicitNumericConversion = new NumericOrEnumerationConversion(true, false);
41    public static readonly Conversion ExplicitNumericConversion = new NumericOrEnumerationConversion(false, false);
42    public static readonly Conversion ImplicitLiftedNumericConversion = new NumericOrEnumerationConversion(true, true);
43    public static readonly Conversion ExplicitLiftedNumericConversion = new NumericOrEnumerationConversion(false, true);
44   
45    public static Conversion EnumerationConversion(bool isImplicit, bool isLifted)
46    {
47      return new NumericOrEnumerationConversion(isImplicit, isLifted, true);
48    }
49   
50    public static readonly Conversion NullLiteralConversion = new BuiltinConversion(true, 1);
51   
52    /// <summary>
53    /// The numeric conversion of a constant expression.
54    /// </summary>
55    public static readonly Conversion ImplicitConstantExpressionConversion = new BuiltinConversion(true, 2);
56   
57    public static readonly Conversion ImplicitReferenceConversion = new BuiltinConversion(true, 3);
58    public static readonly Conversion ExplicitReferenceConversion = new BuiltinConversion(false, 3);
59   
60    public static readonly Conversion ImplicitDynamicConversion = new BuiltinConversion(true, 4);
61    public static readonly Conversion ExplicitDynamicConversion = new BuiltinConversion(false, 4);
62   
63    public static readonly Conversion ImplicitNullableConversion = new BuiltinConversion(true, 5);
64    public static readonly Conversion ExplicitNullableConversion = new BuiltinConversion(false, 5);
65   
66    public static readonly Conversion ImplicitPointerConversion = new BuiltinConversion(true, 6);
67    public static readonly Conversion ExplicitPointerConversion = new BuiltinConversion(false, 6);
68   
69    public static readonly Conversion BoxingConversion = new BuiltinConversion(true, 7);
70    public static readonly Conversion UnboxingConversion = new BuiltinConversion(false, 8);
71   
72    /// <summary>
73    /// C# 'as' cast.
74    /// </summary>
75    public static readonly Conversion TryCast = new BuiltinConversion(false, 9);
76   
77    [Obsolete("Use UserDefinedConversion() instead")]
78    public static Conversion UserDefinedImplicitConversion(IMethod operatorMethod, Conversion conversionBeforeUserDefinedOperator, Conversion conversionAfterUserDefinedOperator, bool isLifted)
79    {
80      if (operatorMethod == null)
81        throw new ArgumentNullException("operatorMethod");
82      return new UserDefinedConv(true, operatorMethod, conversionBeforeUserDefinedOperator, conversionAfterUserDefinedOperator, isLifted, false);
83    }
84   
85    [Obsolete("Use UserDefinedConversion() instead")]
86    public static Conversion UserDefinedExplicitConversion(IMethod operatorMethod, Conversion conversionBeforeUserDefinedOperator, Conversion conversionAfterUserDefinedOperator, bool isLifted)
87    {
88      if (operatorMethod == null)
89        throw new ArgumentNullException("operatorMethod");
90      return new UserDefinedConv(false, operatorMethod, conversionBeforeUserDefinedOperator, conversionAfterUserDefinedOperator, isLifted, false);
91    }
92   
93    public static Conversion UserDefinedConversion(IMethod operatorMethod, bool isImplicit, Conversion conversionBeforeUserDefinedOperator, Conversion conversionAfterUserDefinedOperator, bool isLifted = false, bool isAmbiguous = false)
94    {
95      if (operatorMethod == null)
96        throw new ArgumentNullException("operatorMethod");
97      return new UserDefinedConv(isImplicit, operatorMethod, conversionBeforeUserDefinedOperator, conversionAfterUserDefinedOperator, isLifted, isAmbiguous);
98    }
99   
100    public static Conversion MethodGroupConversion(IMethod chosenMethod, bool isVirtualMethodLookup, bool delegateCapturesFirstArgument)
101    {
102      if (chosenMethod == null)
103        throw new ArgumentNullException("chosenMethod");
104      return new MethodGroupConv(chosenMethod, isVirtualMethodLookup, delegateCapturesFirstArgument, isValid: true);
105    }
106   
107    public static Conversion InvalidMethodGroupConversion(IMethod chosenMethod, bool isVirtualMethodLookup, bool delegateCapturesFirstArgument)
108    {
109      if (chosenMethod == null)
110        throw new ArgumentNullException("chosenMethod");
111      return new MethodGroupConv(chosenMethod, isVirtualMethodLookup, delegateCapturesFirstArgument, isValid: false);
112    }
113    #endregion
114   
115    #region Inner classes
116    sealed class InvalidConversion : Conversion
117    {
118      public override bool IsValid {
119        get { return false; }
120      }
121     
122      public override string ToString()
123      {
124        return "None";
125      }
126    }
127   
128    sealed class NumericOrEnumerationConversion : Conversion
129    {
130      readonly bool isImplicit;
131      readonly bool isLifted;
132      readonly bool isEnumeration;
133     
134      public NumericOrEnumerationConversion(bool isImplicit, bool isLifted, bool isEnumeration = false)
135      {
136        this.isImplicit = isImplicit;
137        this.isLifted = isLifted;
138        this.isEnumeration = isEnumeration;
139      }
140     
141      public override bool IsImplicit {
142        get { return isImplicit; }
143      }
144     
145      public override bool IsExplicit {
146        get { return !isImplicit; }
147      }
148     
149      public override bool IsNumericConversion {
150        get { return !isEnumeration; }
151      }
152     
153      public override bool IsEnumerationConversion {
154        get { return isEnumeration; }
155      }
156     
157      public override bool IsLifted {
158        get { return isLifted; }
159      }
160     
161      public override string ToString()
162      {
163        return (isImplicit ? "implicit" : "explicit")
164          + (isLifted ? " lifted" : "")
165          + (isEnumeration ? " enumeration" : " numeric")
166          + " conversion";
167      }
168     
169      public override bool Equals(Conversion other)
170      {
171        NumericOrEnumerationConversion o = other as NumericOrEnumerationConversion;
172        return o != null && isImplicit == o.isImplicit && isLifted == o.isLifted && isEnumeration == o.isEnumeration;
173      }
174     
175      public override int GetHashCode()
176      {
177        return (isImplicit ? 1 : 0) + (isLifted ? 2 : 0) + (isEnumeration ? 4 : 0);
178      }
179    }
180   
181    sealed class BuiltinConversion : Conversion
182    {
183      readonly bool isImplicit;
184      readonly byte type;
185     
186      public BuiltinConversion(bool isImplicit, byte type)
187      {
188        this.isImplicit = isImplicit;
189        this.type = type;
190      }
191     
192      public override bool IsImplicit {
193        get { return isImplicit; }
194      }
195     
196      public override bool IsExplicit {
197        get { return !isImplicit; }
198      }
199     
200      public override bool IsIdentityConversion {
201        get { return type == 0; }
202      }
203     
204      public override bool IsNullLiteralConversion {
205        get { return type == 1; }
206      }
207     
208      public override bool IsConstantExpressionConversion {
209        get { return type == 2; }
210      }
211
212      public override bool IsReferenceConversion {
213        get { return type == 3; }
214      }
215     
216      public override bool IsDynamicConversion {
217        get { return type == 4; }
218      }
219     
220      public override bool IsNullableConversion {
221        get { return type == 5; }
222      }
223     
224      public override bool IsPointerConversion {
225        get { return type == 6; }
226      }
227     
228      public override bool IsBoxingConversion {
229        get { return type == 7; }
230      }
231     
232      public override bool IsUnboxingConversion {
233        get { return type == 8; }
234      }
235     
236      public override bool IsTryCast {
237        get { return type == 9; }
238      }
239     
240      public override string ToString()
241      {
242        string name = null;
243        switch (type) {
244          case 0:
245            return "identity conversion";
246          case 1:
247            return "null-literal conversion";
248          case 2:
249            name = "constant-expression";
250            break;
251          case 3:
252            name = "reference";
253            break;
254          case 4:
255            name = "dynamic";
256            break;
257          case 5:
258            name = "nullable";
259            break;
260          case 6:
261            name = "pointer";
262            break;
263          case 7:
264            return "boxing conversion";
265          case 8:
266            return "unboxing conversion";
267          case 9:
268            return "try cast";
269        }
270        return (isImplicit ? "implicit " : "explicit ") + name + " conversion";
271      }
272    }
273   
274    sealed class UserDefinedConv : Conversion
275    {
276      readonly IMethod method;
277      readonly bool isLifted;
278      readonly Conversion conversionBeforeUserDefinedOperator;
279      readonly Conversion conversionAfterUserDefinedOperator;
280      readonly bool isImplicit;
281      readonly bool isValid;
282     
283      public UserDefinedConv(bool isImplicit, IMethod method, Conversion conversionBeforeUserDefinedOperator, Conversion conversionAfterUserDefinedOperator, bool isLifted, bool isAmbiguous)
284      {
285        this.method = method;
286        this.isLifted = isLifted;
287        this.conversionBeforeUserDefinedOperator = conversionBeforeUserDefinedOperator;
288        this.conversionAfterUserDefinedOperator = conversionAfterUserDefinedOperator;
289        this.isImplicit = isImplicit;
290        this.isValid = !isAmbiguous;
291      }
292     
293      public override bool IsValid {
294        get { return isValid; }
295      }
296     
297      public override bool IsImplicit {
298        get { return isImplicit; }
299      }
300     
301      public override bool IsExplicit {
302        get { return !isImplicit; }
303      }
304     
305      public override bool IsLifted {
306        get { return isLifted; }
307      }
308     
309      public override bool IsUserDefined {
310        get { return true; }
311      }
312     
313      public override Conversion ConversionBeforeUserDefinedOperator {
314        get { return conversionBeforeUserDefinedOperator; }
315      }
316   
317      public override Conversion ConversionAfterUserDefinedOperator {
318        get { return conversionAfterUserDefinedOperator; }
319      }
320
321      public override IMethod Method {
322        get { return method; }
323      }
324     
325      public override bool Equals(Conversion other)
326      {
327        UserDefinedConv o = other as UserDefinedConv;
328        return o != null && isLifted == o.isLifted && isImplicit == o.isImplicit && isValid == o.isValid && method.Equals(o.method);
329      }
330     
331      public override int GetHashCode()
332      {
333        return unchecked(method.GetHashCode() + (isLifted ? 31 : 27) + (isImplicit ? 71 : 61) + (isValid ? 107 : 109));
334      }
335     
336      public override string ToString()
337      {
338        return (isImplicit ? "implicit" : "explicit")
339          + (isLifted ? " lifted" : "")
340          + (isValid ? "" : " ambiguous")
341          + "user-defined conversion (" + method + ")";
342      }
343    }
344   
345    sealed class MethodGroupConv : Conversion
346    {
347      readonly IMethod method;
348      readonly bool isVirtualMethodLookup;
349      readonly bool delegateCapturesFirstArgument;
350      readonly bool isValid;
351     
352      public MethodGroupConv(IMethod method, bool isVirtualMethodLookup, bool delegateCapturesFirstArgument, bool isValid)
353      {
354        this.method = method;
355        this.isVirtualMethodLookup = isVirtualMethodLookup;
356        this.delegateCapturesFirstArgument = delegateCapturesFirstArgument;
357        this.isValid = isValid;
358      }
359     
360      public override bool IsValid {
361        get { return isValid; }
362      }
363     
364      public override bool IsImplicit {
365        get { return true; }
366      }
367     
368      public override bool IsMethodGroupConversion {
369        get { return true; }
370      }
371     
372      public override bool IsVirtualMethodLookup {
373        get { return isVirtualMethodLookup; }
374      }
375     
376      public override bool DelegateCapturesFirstArgument {
377        get { return delegateCapturesFirstArgument; }
378      }
379
380      public override IMethod Method {
381        get { return method; }
382      }
383     
384      public override bool Equals(Conversion other)
385      {
386        MethodGroupConv o = other as MethodGroupConv;
387        return o != null && method.Equals(o.method);
388      }
389     
390      public override int GetHashCode()
391      {
392        return method.GetHashCode();
393      }
394    }
395    #endregion
396   
397    /// <summary>
398    /// Gets whether the conversion is valid.
399    /// </summary>
400    public virtual bool IsValid {
401      get { return true; }
402    }
403   
404    public virtual bool IsImplicit {
405      get { return false; }
406    }
407   
408    public virtual bool IsExplicit {
409      get { return false; }
410    }
411   
412    /// <summary>
413    /// Gets whether the conversion is an '<c>as</c>' cast.
414    /// </summary>
415    public virtual bool IsTryCast {
416      get { return false; }
417    }
418   
419    public virtual bool IsIdentityConversion {
420      get { return false; }
421    }
422   
423    public virtual bool IsNullLiteralConversion {
424      get { return false; }
425    }
426   
427    public virtual bool IsConstantExpressionConversion {
428      get { return false; }
429    }
430
431    public virtual bool IsNumericConversion {
432      get { return false; }
433    }
434   
435    /// <summary>
436    /// Gets whether this conversion is a lifted version of another conversion.
437    /// </summary>
438    public virtual bool IsLifted {
439      get { return false; }
440    }
441   
442    /// <summary>
443    /// Gets whether the conversion is dynamic.
444    /// </summary>
445    public virtual bool IsDynamicConversion {
446      get { return false; }
447    }
448   
449    /// <summary>
450    /// Gets whether the conversion is a reference conversion.
451    /// </summary>
452    public virtual bool IsReferenceConversion {
453      get { return false; }
454    }
455   
456    /// <summary>
457    /// Gets whether the conversion is an enumeration conversion.
458    /// </summary>
459    public virtual bool IsEnumerationConversion {
460      get { return false; }
461    }
462   
463    /// <summary>
464    /// Gets whether the conversion is a nullable conversion
465    /// (conversion between a nullable type and the regular type).
466    /// </summary>
467    public virtual bool IsNullableConversion {
468      get { return false; }
469    }
470   
471    /// <summary>
472    /// Gets whether this conversion is user-defined (op_Implicit or op_Explicit).
473    /// </summary>
474    public virtual bool IsUserDefined {
475      get { return false; }
476    }
477
478    /// <summary>
479    /// The conversion that is applied to the input before the user-defined conversion operator is invoked.
480    /// </summary>
481    public virtual Conversion ConversionBeforeUserDefinedOperator {
482      get { return null; }
483    }
484   
485    /// <summary>
486    /// The conversion that is applied to the result of the user-defined conversion operator.
487    /// </summary>
488    public virtual Conversion ConversionAfterUserDefinedOperator {
489      get { return null; }
490    }
491
492    /// <summary>
493    /// Gets whether this conversion is a boxing conversion.
494    /// </summary>
495    public virtual bool IsBoxingConversion {
496      get { return false; }
497    }
498   
499    /// <summary>
500    /// Gets whether this conversion is an unboxing conversion.
501    /// </summary>
502    public virtual bool IsUnboxingConversion {
503      get { return false; }
504    }
505   
506    /// <summary>
507    /// Gets whether this conversion is a pointer conversion.
508    /// </summary>
509    public virtual bool IsPointerConversion {
510      get { return false; }
511    }
512   
513    /// <summary>
514    /// Gets whether this conversion is a method group conversion.
515    /// </summary>
516    public virtual bool IsMethodGroupConversion {
517      get { return false; }
518    }
519   
520    /// <summary>
521    /// For method-group conversions, gets whether to perform a virtual method lookup at runtime.
522    /// </summary>
523    public virtual bool IsVirtualMethodLookup {
524      get { return false; }
525    }
526   
527    /// <summary>
528    /// For method-group conversions, gets whether the conversion captures the first argument.
529    ///
530    /// For instance methods, this property always returns true for C# method-group conversions.
531    /// For static methods, this property returns true for method-group conversions of an extension method performed on an instance (eg. <c>Func&lt;int&gt; f = myEnumerable.Single</c>).
532    /// </summary>
533    public virtual bool DelegateCapturesFirstArgument {
534      get { return false; }
535    }
536
537    /// <summary>
538    /// Gets whether this conversion is an anonymous function conversion.
539    /// </summary>
540    public virtual bool IsAnonymousFunctionConversion {
541      get { return false; }
542    }
543   
544    /// <summary>
545    /// Gets the method associated with this conversion.
546    /// For user-defined conversions, this is the method being called.
547    /// For method-group conversions, this is the method that was chosen from the group.
548    /// </summary>
549    public virtual IMethod Method {
550      get { return null; }
551    }
552   
553    public override sealed bool Equals(object obj)
554    {
555      return Equals(obj as Conversion);
556    }
557   
558    public override int GetHashCode()
559    {
560      return base.GetHashCode();
561    }
562   
563    public virtual bool Equals(Conversion other)
564    {
565      return this == other;
566    }
567  }
568}
Note: See TracBrowser for help on using the repository browser.