* Makefile.am:
[monodevelop.git] / extras / MonoDevelop.Debugger.Mdb / Mono.Debugging.Server.Mdb / Convert.cs
blob2b68efc8b5db55759623970b3b25a342704cd0bb
1 // Convert.cs
2 //
3 // Author:
4 // Lluis Sanchez Gual <lluis@novell.com>
5 //
6 // Copyright (c) 2008 Novell, Inc (http://www.novell.com)
7 //
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
24 // THE SOFTWARE.
28 using System;
29 using Mono.Debugger;
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.
42 switch (skind) {
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))
49 return true;
50 break;
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))
61 return true;
62 break;
64 case FundamentalKind.Int16:
65 if ((tkind == FundamentalKind.Int32) ||
66 (tkind == FundamentalKind.Int64) ||
67 (tkind == FundamentalKind.Single) ||
68 (tkind == FundamentalKind.Double))
69 return true;
70 break;
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))
79 return true;
80 break;
82 case FundamentalKind.Int32:
83 if ((tkind == FundamentalKind.Int64) ||
84 (tkind == FundamentalKind.Single) ||
85 (tkind == FundamentalKind.Double))
86 return true;
87 break;
89 case FundamentalKind.UInt32:
90 if ((tkind == FundamentalKind.Int64) ||
91 (tkind == FundamentalKind.UInt64) ||
92 (tkind == FundamentalKind.Single) ||
93 (tkind == FundamentalKind.Double))
94 return true;
95 break;
97 case FundamentalKind.Int64:
98 case FundamentalKind.UInt64:
99 if ((tkind == FundamentalKind.Single) ||
100 (tkind == FundamentalKind.Double))
101 return true;
102 break;
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))
112 return true;
113 break;
115 case FundamentalKind.Single:
116 if (tkind == FundamentalKind.Double)
117 return true;
118 break;
120 default:
121 break;
124 return false;
127 static bool ImplicitFundamentalConversionExists (TargetFundamentalType source, TargetFundamentalType target)
129 return ImplicitFundamentalConversionExists (
130 source.FundamentalKind, target.FundamentalKind);
133 static object ImplicitFundamentalConversion (object value, FundamentalKind tkind)
135 switch (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);
160 default:
161 return null;
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))
173 return null;
175 object value = obj.GetObject (ctx.Thread);
177 object new_value = ImplicitFundamentalConversion (value, tkind);
178 if (new_value == null)
179 return 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);
189 if (retval != null)
190 return retval;
192 FundamentalKind tkind = type.FundamentalKind;
194 try {
195 object value = obj.GetObject (ctx.Thread);
196 object new_value = ImplicitFundamentalConversion (value, tkind);
197 if (new_value == null)
198 return null;
200 return type.Language.CreateInstance (ctx.Thread, new_value);
201 } catch {
202 return null;
206 static bool ImplicitReferenceConversionExists (EvaluationContext ctx,
207 TargetStructType source,
208 TargetStructType target)
210 if (source == target)
211 return true;
213 if (!source.HasParent)
214 return false;
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)
225 return obj;
227 if (!obj.Type.HasParent)
228 return null;
230 TargetObject pobj = obj.GetParentObject (ctx.Thread);
231 if (pobj != null)
232 return ImplicitConversion (ctx, pobj, type);
233 else
234 return null;
237 public static bool ImplicitConversionExists (EvaluationContext ctx,
238 TargetType source, TargetType target)
240 if (source.Equals (target))
241 return true;
243 if (source is TargetArrayType && target.Name == "System.Array")
244 return true;
246 if (ObjectUtil.FixTypeName (target.Name) == "System.Object")
247 return true;
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))
258 return true;
261 if (target is TargetEnumType) {
262 TargetEnumType e = (TargetEnumType) target;
263 if (ImplicitConversionExists (ctx, source, e.Value.Type))
264 return true;
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);
277 return false;
280 public static TargetObject ImplicitConversion (EvaluationContext ctx,
281 TargetObject obj, TargetType type)
283 if (obj.Type.Equals (type))
284 return obj;
286 if (type is TargetObjectType || ObjectUtil.FixTypeName (type.Name) == "System.Object") {
287 if (obj.Type.IsByRef)
288 return obj;
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") {
303 return obj;
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))
310 return obj;
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);
324 return null;
327 public static TargetObject ImplicitConversionRequired (EvaluationContext ctx,
328 TargetObject obj, TargetType type)
330 TargetObject new_obj = ImplicitConversion (ctx, obj, type);
331 if (new_obj != null)
332 return new_obj;
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;
340 if (ctype != null)
341 return ctype;
343 TargetObjectType otype = type as TargetObjectType;
344 if (otype != null && otype.HasClassType) {
345 ctype = otype.ClassType;
346 if (ctype != null)
347 return ctype;
350 TargetArrayType atype = type as TargetArrayType;
351 if (atype != null) {
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;
362 if (cobj != null)
363 return cobj;
365 TargetObjectObject oobj = obj as TargetObjectObject;
366 if (oobj != null)
367 return oobj.GetClassObject (ctx.Thread);
369 TargetArrayObject aobj = obj as TargetArrayObject;
370 if ((aobj != null) && aobj.HasClassObject)
371 return aobj.GetClassObject (ctx.Thread);
373 return null;
376 public static TargetStructObject ToStructObject (EvaluationContext ctx, TargetObject obj)
378 TargetStructObject sobj = obj as TargetStructObject;
379 if (sobj != null)
380 return sobj;
382 TargetObjectObject oobj = obj as TargetObjectObject;
383 if (oobj != null)
384 return oobj.GetClassObject (ctx.Thread);
386 TargetArrayObject aobj = obj as TargetArrayObject;
387 if ((aobj != null) && aobj.HasClassObject)
388 return aobj.GetClassObject (ctx.Thread);
390 return null;
393 public static TargetObject Cast (EvaluationContext ctx, TargetObject obj, TargetType targetType)
395 obj = ObjectUtil.GetRealObject (ctx, obj);
397 if (obj.Type == targetType)
398 return obj;
400 if (targetType is TargetObjectType || ObjectUtil.FixTypeName (targetType.Name) == "System.Object") {
401 if (obj.Type.IsByRef)
402 return obj;
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;
411 if (fobj == null)
412 throw new NotSupportedException ();
414 TargetFundamentalType ftype = targetType as TargetFundamentalType;
415 TargetObject ob = ExplicitFundamentalConversion (ctx, fobj, ftype);
416 if (ob == null)
417 throw new NotSupportedException ();
418 return ob;
421 TargetClassType ctype = ToClassType (targetType);
422 TargetClassObject source = ToClassObject (ctx, obj);
424 if (source == null)
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)
438 return source;
440 if (!source_type.HasParent)
441 return null;
443 TargetStructType parent_type = source_type.GetParentType (ctx.Thread);
444 source = TryParentCast (ctx, source, parent_type, target_type);
445 if (source == null)
446 return null;
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);
454 if (current == null)
455 return null;
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)
463 return source;
465 TargetClassObject sobj = ToClassObject (ctx, source);
466 if (sobj == null)
467 return null;
469 TargetStructObject result = TryParentCast (ctx, sobj, sobj.Type, target_type);
470 if (result != null)
471 return result;
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)
479 return true;
481 if (!source_type.HasParent)
482 return false;
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)
491 return true;
493 TargetClassType stype = ToClassType (source);
494 if (stype == null)
495 return false;
497 return TryParentCast (ctx, stype, target_type);