4 // Lluis Sanchez Gual <lluis@novell.com>
6 // Copyright (c) 2008 Novell, Inc (http://www.novell.com)
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
30 using Mono
.Debugger
.Languages
;
32 namespace DebuggerServer
34 public static class TargetObjectConvert
36 static bool ImplicitFundamentalConversionExists (FundamentalKind skind
,
37 FundamentalKind tkind
)
40 // See Convert.ImplicitStandardConversionExists in MCS.
43 case FundamentalKind
.SByte
:
44 if ((tkind
== FundamentalKind
.Int16
) ||
45 (tkind
== FundamentalKind
.Int32
) ||
46 (tkind
== FundamentalKind
.Int64
) ||
47 (tkind
== FundamentalKind
.Single
) ||
48 (tkind
== FundamentalKind
.Double
))
52 case FundamentalKind
.Byte
:
53 if ((tkind
== FundamentalKind
.Int16
) ||
54 (tkind
== FundamentalKind
.UInt16
) ||
55 (tkind
== FundamentalKind
.Int32
) ||
56 (tkind
== FundamentalKind
.UInt32
) ||
57 (tkind
== FundamentalKind
.Int64
) ||
58 (tkind
== FundamentalKind
.UInt64
) ||
59 (tkind
== FundamentalKind
.Single
) ||
60 (tkind
== FundamentalKind
.Double
))
64 case FundamentalKind
.Int16
:
65 if ((tkind
== FundamentalKind
.Int32
) ||
66 (tkind
== FundamentalKind
.Int64
) ||
67 (tkind
== FundamentalKind
.Single
) ||
68 (tkind
== FundamentalKind
.Double
))
72 case FundamentalKind
.UInt16
:
73 if ((tkind
== FundamentalKind
.Int32
) ||
74 (tkind
== FundamentalKind
.UInt32
) ||
75 (tkind
== FundamentalKind
.Int64
) ||
76 (tkind
== FundamentalKind
.UInt64
) ||
77 (tkind
== FundamentalKind
.Single
) ||
78 (tkind
== FundamentalKind
.Double
))
82 case FundamentalKind
.Int32
:
83 if ((tkind
== FundamentalKind
.Int64
) ||
84 (tkind
== FundamentalKind
.Single
) ||
85 (tkind
== FundamentalKind
.Double
))
89 case FundamentalKind
.UInt32
:
90 if ((tkind
== FundamentalKind
.Int64
) ||
91 (tkind
== FundamentalKind
.UInt64
) ||
92 (tkind
== FundamentalKind
.Single
) ||
93 (tkind
== FundamentalKind
.Double
))
97 case FundamentalKind
.Int64
:
98 case FundamentalKind
.UInt64
:
99 if ((tkind
== FundamentalKind
.Single
) ||
100 (tkind
== FundamentalKind
.Double
))
104 case FundamentalKind
.Char
:
105 if ((tkind
== FundamentalKind
.UInt16
) ||
106 (tkind
== FundamentalKind
.Int32
) ||
107 (tkind
== FundamentalKind
.UInt32
) ||
108 (tkind
== FundamentalKind
.Int64
) ||
109 (tkind
== FundamentalKind
.UInt64
) ||
110 (tkind
== FundamentalKind
.Single
) ||
111 (tkind
== FundamentalKind
.Double
))
115 case FundamentalKind
.Single
:
116 if (tkind
== FundamentalKind
.Double
)
127 static bool ImplicitFundamentalConversionExists (TargetFundamentalType source
, TargetFundamentalType target
)
129 return ImplicitFundamentalConversionExists (
130 source
.FundamentalKind
, target
.FundamentalKind
);
133 static object ImplicitFundamentalConversion (object value, FundamentalKind tkind
)
136 case FundamentalKind
.Char
:
137 return System
.Convert
.ToChar (value);
138 case FundamentalKind
.SByte
:
139 return System
.Convert
.ToSByte (value);
140 case FundamentalKind
.Byte
:
141 return System
.Convert
.ToByte (value);
142 case FundamentalKind
.Int16
:
143 return System
.Convert
.ToInt16 (value);
144 case FundamentalKind
.UInt16
:
145 return System
.Convert
.ToUInt16 (value);
146 case FundamentalKind
.Int32
:
147 return System
.Convert
.ToInt32 (value);
148 case FundamentalKind
.UInt32
:
149 return System
.Convert
.ToUInt32 (value);
150 case FundamentalKind
.Int64
:
151 return System
.Convert
.ToInt64 (value);
152 case FundamentalKind
.UInt64
:
153 return System
.Convert
.ToUInt64 (value);
154 case FundamentalKind
.Single
:
155 return System
.Convert
.ToSingle (value);
156 case FundamentalKind
.Double
:
157 return System
.Convert
.ToDouble (value);
158 case FundamentalKind
.String
:
159 return System
.Convert
.ToString (value);
165 static TargetObject
ImplicitFundamentalConversion (EvaluationContext ctx
,
166 TargetFundamentalObject obj
,
167 TargetFundamentalType type
)
169 FundamentalKind skind
= obj
.Type
.FundamentalKind
;
170 FundamentalKind tkind
= type
.FundamentalKind
;
172 if (!ImplicitFundamentalConversionExists (skind
, tkind
))
175 object value = obj
.GetObject (ctx
.Thread
);
177 object new_value
= ImplicitFundamentalConversion (value, tkind
);
178 if (new_value
== null)
181 return type
.Language
.CreateInstance (ctx
.Thread
, new_value
);
184 public static TargetObject
ExplicitFundamentalConversion (EvaluationContext ctx
,
185 TargetFundamentalObject obj
,
186 TargetFundamentalType type
)
188 TargetObject retval
= ImplicitFundamentalConversion (ctx
, obj
, type
);
192 FundamentalKind tkind
= type
.FundamentalKind
;
195 object value = obj
.GetObject (ctx
.Thread
);
196 object new_value
= ImplicitFundamentalConversion (value, tkind
);
197 if (new_value
== null)
200 return type
.Language
.CreateInstance (ctx
.Thread
, new_value
);
206 static bool ImplicitReferenceConversionExists (EvaluationContext ctx
,
207 TargetStructType source
,
208 TargetStructType target
)
210 if (source
== target
)
213 if (!source
.HasParent
)
216 TargetStructType parent_type
= source
.GetParentType (ctx
.Thread
);
217 return ImplicitReferenceConversionExists (ctx
, parent_type
, target
);
220 static TargetObject
ImplicitReferenceConversion (EvaluationContext ctx
,
221 TargetClassObject obj
,
222 TargetClassType type
)
224 if (obj
.Type
== type
)
227 if (!obj
.Type
.HasParent
)
230 TargetObject pobj
= obj
.GetParentObject (ctx
.Thread
);
232 return ImplicitConversion (ctx
, pobj
, type
);
237 public static bool ImplicitConversionExists (EvaluationContext ctx
,
238 TargetType source
, TargetType target
)
240 if (source
.Equals (target
))
243 if (source
is TargetArrayType
&& target
.Name
== "System.Array")
246 if (ObjectUtil
.FixTypeName (target
.Name
) == "System.Object")
249 if (source
is TargetArrayType
&& target
is TargetArrayType
) {
250 TargetArrayType sa
= (TargetArrayType
) source
;
251 TargetArrayType ta
= (TargetArrayType
) target
;
252 return sa
.ElementType
.Equals (ta
.ElementType
);
255 if (source
is TargetEnumType
) {
256 TargetEnumType e
= (TargetEnumType
) source
;
257 if (ImplicitConversionExists (ctx
, e
.Value
.Type
, target
))
261 if (target
is TargetEnumType
) {
262 TargetEnumType e
= (TargetEnumType
) target
;
263 if (ImplicitConversionExists (ctx
, source
, e
.Value
.Type
))
267 if ((source
is TargetFundamentalType
) && (target
is TargetFundamentalType
))
268 return ImplicitFundamentalConversionExists (
269 (TargetFundamentalType
) source
,
270 (TargetFundamentalType
) target
);
272 if ((source
is TargetClassType
) && (target
is TargetClassType
))
273 return ImplicitReferenceConversionExists (
274 ctx
, (TargetClassType
) source
,
275 (TargetClassType
) target
);
280 public static TargetObject
ImplicitConversion (EvaluationContext ctx
,
281 TargetObject obj
, TargetType type
)
283 if (obj
.Type
.Equals (type
))
286 if (type
is TargetObjectType
|| ObjectUtil
.FixTypeName (type
.Name
) == "System.Object") {
287 if (obj
.Type
.IsByRef
)
289 return BoxValue (ctx
, obj
);
292 if (obj
is TargetEnumObject
&& type
is TargetFundamentalType
) {
293 TargetEnumObject e
= (TargetEnumObject
) obj
;
294 return ImplicitConversion (ctx
, e
.GetValue (ctx
.Thread
), type
);
297 if (type
is TargetEnumType
) {
298 TargetEnumType e
= (TargetEnumType
) type
;
299 return ImplicitConversion (ctx
, obj
, e
.Value
.Type
);
302 if (obj
is TargetArrayObject
&& type
.Name
== "System.Array") {
306 if (obj
is TargetArrayObject
&& type
is TargetArrayType
) {
307 TargetArrayObject sa
= (TargetArrayObject
) obj
;
308 TargetArrayType ta
= (TargetArrayType
) type
;
309 if (sa
.Type
.ElementType
.Equals (ta
.ElementType
))
313 if ((obj
is TargetFundamentalObject
) && (type
is TargetFundamentalType
))
314 return ImplicitFundamentalConversion (
315 ctx
, (TargetFundamentalObject
) obj
,
316 (TargetFundamentalType
) type
);
318 if ((obj
is TargetClassObject
) && (type
is TargetClassType
)) {
319 return ImplicitReferenceConversion (
320 ctx
, (TargetClassObject
) obj
,
321 (TargetClassType
) type
);
327 public static TargetObject
ImplicitConversionRequired (EvaluationContext ctx
,
328 TargetObject obj
, TargetType type
)
330 TargetObject new_obj
= ImplicitConversion (ctx
, obj
, type
);
334 throw new Exception (string.Format ("Cannot implicitly convert `{0}' to `{1}'", obj
.Type
.Name
, type
.Name
));
337 public static TargetClassType
ToClassType (TargetType type
)
339 TargetClassType ctype
= type
as TargetClassType
;
343 TargetObjectType otype
= type
as TargetObjectType
;
344 if (otype
!= null && otype
.HasClassType
) {
345 ctype
= otype
.ClassType
;
350 TargetArrayType atype
= type
as TargetArrayType
;
352 if (atype
.Language
.ArrayType
!= null)
353 return atype
.Language
.ArrayType
;
356 throw new Exception (string.Format ("Type `{0}' is not a struct or class.", type
.Name
));
359 public static TargetClassObject
ToClassObject (EvaluationContext ctx
, TargetObject obj
)
361 TargetClassObject cobj
= obj
as TargetClassObject
;
365 TargetObjectObject oobj
= obj
as TargetObjectObject
;
367 return oobj
.GetClassObject (ctx
.Thread
);
369 TargetArrayObject aobj
= obj
as TargetArrayObject
;
370 if ((aobj
!= null) && aobj
.HasClassObject
)
371 return aobj
.GetClassObject (ctx
.Thread
);
376 public static TargetStructObject
ToStructObject (EvaluationContext ctx
, TargetObject obj
)
378 TargetStructObject sobj
= obj
as TargetStructObject
;
382 TargetObjectObject oobj
= obj
as TargetObjectObject
;
384 return oobj
.GetClassObject (ctx
.Thread
);
386 TargetArrayObject aobj
= obj
as TargetArrayObject
;
387 if ((aobj
!= null) && aobj
.HasClassObject
)
388 return aobj
.GetClassObject (ctx
.Thread
);
393 public static TargetObject
Cast (EvaluationContext ctx
, TargetObject obj
, TargetType targetType
)
395 obj
= ObjectUtil
.GetRealObject (ctx
, obj
);
397 if (obj
.Type
== targetType
)
400 if (targetType
is TargetObjectType
|| ObjectUtil
.FixTypeName (targetType
.Name
) == "System.Object") {
401 if (obj
.Type
.IsByRef
)
403 return BoxValue (ctx
, obj
);
406 if (targetType
is TargetPointerType
)
407 throw new NotSupportedException ();
409 if (targetType
is TargetFundamentalType
) {
410 TargetFundamentalObject fobj
= obj
as TargetFundamentalObject
;
412 throw new NotSupportedException ();
414 TargetFundamentalType ftype
= targetType
as TargetFundamentalType
;
415 TargetObject ob
= ExplicitFundamentalConversion (ctx
, fobj
, ftype
);
417 throw new NotSupportedException ();
421 TargetClassType ctype
= ToClassType (targetType
);
422 TargetClassObject source
= ToClassObject (ctx
, obj
);
425 throw new Exception (string.Format ("Variable is not a class type."));
427 return TryCast (ctx
, source
, ctype
);
430 static TargetObject
BoxValue (EvaluationContext ctx
, TargetObject fobj
)
432 return ctx
.Frame
.Language
.CreateBoxedObject (ctx
.Thread
, fobj
);
435 static TargetStructObject
TryParentCast (EvaluationContext ctx
, TargetStructObject source
, TargetStructType source_type
, TargetStructType target_type
)
437 if (source_type
== target_type
)
440 if (!source_type
.HasParent
)
443 TargetStructType parent_type
= source_type
.GetParentType (ctx
.Thread
);
444 source
= TryParentCast (ctx
, source
, parent_type
, target_type
);
448 return source
.GetParentObject (ctx
.Thread
) as TargetClassObject
;
451 static TargetStructObject
TryCurrentCast (EvaluationContext ctx
, TargetClassObject source
, TargetClassType target_type
)
453 TargetStructObject current
= source
.GetCurrentObject (ctx
.Thread
);
457 return TryParentCast (ctx
, current
, current
.Type
, target_type
);
460 public static TargetObject
TryCast (EvaluationContext ctx
, TargetObject source
, TargetClassType target_type
)
462 if (source
.Type
== target_type
)
465 TargetClassObject sobj
= ToClassObject (ctx
, source
);
469 TargetStructObject result
= TryParentCast (ctx
, sobj
, sobj
.Type
, target_type
);
473 return TryCurrentCast (ctx
, sobj
, target_type
);
476 static bool TryParentCast (EvaluationContext ctx
, TargetStructType source_type
, TargetStructType target_type
)
478 if (source_type
== target_type
)
481 if (!source_type
.HasParent
)
484 TargetStructType parent_type
= source_type
.GetParentType (ctx
.Thread
);
485 return TryParentCast (ctx
, parent_type
, target_type
);
488 public static bool TryCast (EvaluationContext ctx
, TargetType source
, TargetClassType target_type
)
490 if (source
== target_type
)
493 TargetClassType stype
= ToClassType (source
);
497 return TryParentCast (ctx
, stype
, target_type
);