Added tests for Task.WhenAll w/ empty list
[mono.git] / mcs / class / System.ServiceModel / Mono.CodeGeneration / CodeCast.cs
1 //
2 // Permission is hereby granted, free of charge, to any person obtaining
3 // a copy of this software and associated documentation files (the
4 // "Software"), to deal in the Software without restriction, including
5 // without limitation the rights to use, copy, modify, merge, publish,
6 // distribute, sublicense, and/or sell copies of the Software, and to
7 // permit persons to whom the Software is furnished to do so, subject to
8 // the following conditions:
9 // 
10 // The above copyright notice and this permission notice shall be
11 // included in all copies or substantial portions of the Software.
12 // 
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
15 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
17 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
18 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
19 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 //
21 // Copyright (C) Lluis Sanchez Gual, 2004
22 //
23
24 #if !MONOTOUCH
25 using System;
26 using System.Reflection;
27 using System.Reflection.Emit;
28 using Mono.CodeGeneration;
29
30 namespace Mono.CodeGeneration
31 {
32         public class CodeCast: CodeExpression
33         {
34                 Type type; 
35                 CodeExpression exp;
36                 
37                 public CodeCast (Type type, CodeExpression exp)
38                 {
39                         this.type = type;               
40                         this.exp = exp;
41                 }
42                 
43                 public override void Generate (ILGenerator gen)
44                 {
45                         exp.Generate (gen);
46                         
47                         Type typeObj = exp.GetResultType ();
48
49                         if (type.IsAssignableFrom (typeObj)) {
50                                 if (typeObj.IsValueType)
51                                         gen.Emit (OpCodes.Box, typeObj);
52                                 return;
53                         }
54                         else if (type.IsValueType && typeObj == typeof(object)) {
55                                 // Unbox
56                                 gen.Emit (OpCodes.Unbox, type);
57                                 CodeGenerationHelper.LoadFromPtr (gen, type);
58                                 return;
59                         }
60                         else if (typeObj.IsAssignableFrom (type)) {
61                                 // Sub s = (Sub)base
62                                 gen.Emit (OpCodes.Castclass, type);
63                                 return;
64                         }
65                         else if (CodeGenerationHelper.IsNumber (type) && CodeGenerationHelper.IsNumber (typeObj)) {
66                                 switch (Type.GetTypeCode (type))
67                                 {
68                                         case TypeCode.Byte:
69                                                 gen.Emit (OpCodes.Conv_U1);
70                                                 return;
71                                         case TypeCode.Double:
72                                                 gen.Emit (OpCodes.Conv_R8);
73                                                 return;
74                                         case TypeCode.Int16:
75                                                 gen.Emit (OpCodes.Conv_I2);
76                                                 return;
77                                         case TypeCode.Int32:
78                                                 gen.Emit (OpCodes.Conv_I4);
79                                                 return;
80                                         case TypeCode.Int64:
81                                                 gen.Emit (OpCodes.Conv_I8);
82                                                 return;
83                                         case TypeCode.SByte:
84                                                 gen.Emit (OpCodes.Conv_I1);
85                                                 return;
86                                         case TypeCode.Single:
87                                                 gen.Emit (OpCodes.Conv_R4);
88                                                 return;
89                                         case TypeCode.UInt16:
90                                                 gen.Emit (OpCodes.Conv_U2);
91                                                 return;
92                                         case TypeCode.UInt32:
93                                                 gen.Emit (OpCodes.Conv_U4);
94                                                 return;
95                                         case TypeCode.UInt64:
96                                                 gen.Emit (OpCodes.Conv_U8);
97                                                 return;
98                                 }
99                         }
100                         
101                         MethodInfo imp = type.GetMethod ("op_Implicit", new Type[] { typeObj });
102                         if (imp != null) {
103                                 gen.Emit (OpCodes.Call, imp);
104                                 return;
105                         }
106                         
107                         foreach (MethodInfo m in typeObj.GetMember ("op_Explicit"))
108                                 if (m.ReturnType == type) {
109                                         gen.Emit (OpCodes.Call, m);
110                                         return;
111                                 }
112
113                         throw new InvalidOperationException ("Can't cast from " + typeObj + " to " + type);
114                 }
115                 
116                 public override void PrintCode (CodeWriter cp)
117                 {
118                         Type typeObj = exp.GetResultType ();
119                         if (type.IsAssignableFrom (typeObj)) {
120                                 exp.PrintCode (cp);
121                                 return;
122                         }
123                         
124                         cp.Write ("((" + type.FullName + ") ");
125                         exp.PrintCode (cp);
126                         cp.Write (")");
127                 }
128                 
129                 public override Type GetResultType ()
130                 {
131                         return type;
132                 }
133         }
134 }
135 #endif