Browse Source

Support for array creation

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@5163 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 16 years ago
parent
commit
097349d227
  1. 22
      src/AddIns/Misc/Debugger/Debugger.Core/Eval.cs
  2. 2
      src/AddIns/Misc/Debugger/Debugger.Core/Interop/CorDebug.cs
  3. 6
      src/AddIns/Misc/Debugger/Debugger.Core/Interop/CorDebugExtensionMethods.generated.cs
  4. 2
      src/AddIns/Misc/Debugger/Debugger.Core/MetaData/DebugType.cs
  5. 130
      src/AddIns/Misc/Debugger/Debugger.Core/NRefactory/Visitors/ExpressionEvaluator.cs
  6. 6
      src/AddIns/Misc/Debugger/Debugger.Core/Value.cs

22
src/AddIns/Misc/Debugger/Debugger.Core/Eval.cs

@ -333,6 +333,28 @@ namespace Debugger @@ -333,6 +333,28 @@ namespace Debugger
#region Convenience methods
public static Value NewArray(DebugType type, uint length, uint? lowerBound)
{
return AsyncNewArray(type, length, lowerBound).WaitForResult();
}
#endregion
public static Eval AsyncNewArray(DebugType type, uint length, uint? lowerBound)
{
lowerBound = lowerBound ?? 0;
return new Eval(
type.AppDomain,
"New array: " + type + "[" + length + "]",
delegate(Eval eval) {
// Multi-dimensional arrays not supported in .NET 2.0
eval.CorEval2.NewParameterizedArray(type.CorType, 1, new uint[] { length }, new uint[] { lowerBound.Value });
}
);
}
#region Convenience methods
public static Value NewObject(DebugType debugType, Value[] constructorArguments, DebugType[] constructorArgumentsTypes)
{
return AsyncNewObject(debugType, constructorArguments, constructorArgumentsTypes).WaitForResult();

2
src/AddIns/Misc/Debugger/Debugger.Core/Interop/CorDebug.cs

@ -778,7 +778,7 @@ namespace Debugger.Interop.CorDebug @@ -778,7 +778,7 @@ namespace Debugger.Interop.CorDebug
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)]
void __NewParameterizedObjectNoConstructor([In, MarshalAs(UnmanagedType.Interface)] ICorDebugClass pClass, [In] uint nTypeArgs, [In, MarshalAs(UnmanagedType.LPArray)] ICorDebugType[] ppTypeArgs);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)]
void __NewParameterizedArray([In, MarshalAs(UnmanagedType.Interface)] ICorDebugType pElementType, [In] uint rank, [In] ref uint dims, [In] ref uint lowBounds);
void __NewParameterizedArray([In, MarshalAs(UnmanagedType.Interface)] ICorDebugType pElementType, [In] uint rank, [In, MarshalAs(UnmanagedType.LPArray)] uint[] dims, [In, MarshalAs(UnmanagedType.LPArray)] uint[] lowBounds);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)]
void __NewStringWithLength([In, MarshalAs(UnmanagedType.LPWStr)] string @string, [In] uint uiLength);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)]

6
src/AddIns/Misc/Debugger/Debugger.Core/Interop/CorDebugExtensionMethods.generated.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// <file>
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
@ -1242,9 +1242,9 @@ namespace Debugger.Interop.CorDebug @@ -1242,9 +1242,9 @@ namespace Debugger.Interop.CorDebug
ProcessOutParameter(ppTypeArgs);
}
public static void NewParameterizedArray(this ICorDebugEval2 instance, ICorDebugType pElementType, uint rank, ref uint dims, ref uint lowBounds)
public static void NewParameterizedArray(this ICorDebugEval2 instance, ICorDebugType pElementType, uint rank, uint[] dims, uint[] lowBounds)
{
instance.__NewParameterizedArray(pElementType, rank, ref dims, ref lowBounds);
instance.__NewParameterizedArray(pElementType, rank, dims, lowBounds);
}
public static void NewStringWithLength(this ICorDebugEval2 instance, string @string, uint uiLength)

2
src/AddIns/Misc/Debugger/Debugger.Core/MetaData/DebugType.cs

@ -439,6 +439,8 @@ namespace Debugger.MetaData @@ -439,6 +439,8 @@ namespace Debugger.MetaData
if (this.IsPrimitive && toType.IsPrimitive) {
string f = this.FullName;
string t = toType.FullName;
if (f == t)
return true;
if (f == SByte && (t == Short || t == Int || t == Long || t == Float || t == Double || t == Decimal))
return true;
if (f == Byte && (t == Short || t == UShort || t == Int || t == UInt || t == Long || t == ULong || t == Float || t == Double || t == Decimal))

130
src/AddIns/Misc/Debugger/Debugger.Core/NRefactory/Visitors/ExpressionEvaluator.cs

@ -48,8 +48,16 @@ namespace ICSharpCode.NRefactory.Visitors @@ -48,8 +48,16 @@ namespace ICSharpCode.NRefactory.Visitors
public class ExpressionEvaluator: NotImplementedAstVisitor
{
const BindingFlags BindingFlagsAll = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance;
const BindingFlags BindingFlagsAllDeclared = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance;
StackFrame context;
public StackFrame Context {
get { return context; }
}
ExpressionEvaluator(StackFrame context)
{
this.context = context;
}
public static INode Parse(string code, SupportedLanguage language)
{
@ -194,15 +202,45 @@ namespace ICSharpCode.NRefactory.Visitors @@ -194,15 +202,45 @@ namespace ICSharpCode.NRefactory.Visitors
return val;
}
StackFrame context;
public StackFrame Context {
get { return context; }
int EvaluateAsInt(INode expression)
{
if (expression is PrimitiveExpression) {
int? i = ((PrimitiveExpression)expression).Value as int?;
if (i == null)
throw new EvaluateException(expression, "Integer expected");
return i.Value;
} else {
TypedValue typedVal = Evaluate(expression);
if (typedVal.Type.CanImplicitelyConvertTo(typeof(int))) {
int i = (int)Convert.ChangeType(typedVal.PrimitiveValue, typeof(int));
return i;
} else {
throw new EvaluateException(expression, "Integer expected");
}
}
}
ExpressionEvaluator(StackFrame context)
TypedValue EvaluateAs(INode expression, DebugType type)
{
this.context = context;
TypedValue val = Evaluate(expression);
if (val.Type == type)
return val;
if (!val.Type.CanImplicitelyConvertTo(type))
throw new EvaluateException(expression, "Can not implicitely cast {0} to {1}", val.Type.FullName, type.FullName);
if (type.IsPrimitive) {
object oldVal = val.PrimitiveValue;
object newVal;
try {
newVal = Convert.ChangeType(oldVal, type.PrimitiveType);
} catch (InvalidCastException) {
throw new EvaluateException(expression, "Can not cast {0} to {1}", val.GetType().FullName, type.FullName);
} catch (OverflowException) {
throw new EvaluateException(expression, "Overflow");
}
return CreateValue(newVal);
} else {
return new TypedValue(val.Value, type);
}
}
Value[] GetValues(List<TypedValue> typedVals)
@ -372,40 +410,34 @@ namespace ICSharpCode.NRefactory.Visitors @@ -372,40 +410,34 @@ namespace ICSharpCode.NRefactory.Visitors
{
TypedValue target = Evaluate(indexerExpression.TargetObject);
List<TypedValue> indexes = new List<TypedValue>();
foreach(Expression indexExpr in indexerExpression.Indexes) {
indexes.Add(Evaluate(indexExpr));
}
if (target.Type.IsArray) {
List<int> intIndexes = new List<int>();
foreach(TypedValue index in indexes) {
if (!index.Type.IsInteger)
throw new GetValueException("Integer expected for indexer");
intIndexes.Add((int)index.PrimitiveValue);
foreach(Expression indexExpr in indexerExpression.Indexes) {
intIndexes.Add(EvaluateAsInt(indexExpr));
}
return new TypedValue(
target.Value.GetArrayElement(intIndexes.ToArray()),
(DebugType)target.Type.GetElementType()
);
}
if (target.Type.FullName == typeof(string).FullName) {
if (indexes.Count == 1 && indexes[0].Type.IsInteger) {
int index = (int)indexes[0].PrimitiveValue;
return CreateValue(((string)target.PrimitiveValue)[index]);
} else {
throw new GetValueException("Expected single integer index");
} else if (target.Type.FullName == typeof(string).FullName) {
if (indexerExpression.Indexes.Count != 1)
throw new GetValueException("Single index expected");
int index = EvaluateAsInt(indexerExpression.Indexes[0]);
return CreateValue(((string)target.PrimitiveValue)[index]);
} else {
List<TypedValue> indexes = new List<TypedValue>();
foreach(Expression indexExpr in indexerExpression.Indexes) {
indexes.Add(Evaluate(indexExpr));
}
DebugPropertyInfo pi = (DebugPropertyInfo)target.Type.GetProperty("Item", GetTypes(indexes));
if (pi == null)
throw new GetValueException("The object does not have an indexer property");
return new TypedValue(
target.Value.GetPropertyValue(pi, GetValues(indexes)),
(DebugType)pi.PropertyType
);
}
DebugPropertyInfo pi = (DebugPropertyInfo)target.Type.GetProperty("Item", GetTypes(indexes));
if (pi == null)
throw new GetValueException("The object does not have an indexer property");
return new TypedValue(
target.Value.GetPropertyValue(pi, GetValues(indexes)),
(DebugType)pi.PropertyType
);
}
public override object VisitInvocationExpression(InvocationExpression invocationExpression, object data)
@ -453,19 +485,45 @@ namespace ICSharpCode.NRefactory.Visitors @@ -453,19 +485,45 @@ namespace ICSharpCode.NRefactory.Visitors
public override object VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, object data)
{
if (!objectCreateExpression.ObjectInitializer.IsNull)
throw new EvaluateException(objectCreateExpression.ObjectInitializer, "Object initializers not supported");
DebugType type = objectCreateExpression.CreateType.ResolveType(context.AppDomain);
List<TypedValue> ctorArgs = new List<TypedValue>(objectCreateExpression.Parameters.Count);
foreach(Expression argExpr in objectCreateExpression.Parameters) {
ctorArgs.Add(Evaluate(argExpr));
}
// TODO: Use reflection
// TODO: Arrays
DebugType type = objectCreateExpression.CreateType.ResolveType(context.AppDomain);
return new TypedValue(
Eval.NewObject((DebugType)type, GetValues(ctorArgs), GetTypes(ctorArgs)),
type
);
}
public override object VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, object data)
{
if (arrayCreateExpression.CreateType.RankSpecifier[0] != 0)
throw new EvaluateException(arrayCreateExpression, "Multi-dimensional arrays are not suppored");
DebugType type = arrayCreateExpression.CreateType.ResolveType(context.AppDomain);
int length = 0;
if (arrayCreateExpression.Arguments.Count == 1) {
length = EvaluateAsInt(arrayCreateExpression.Arguments[0]);
} else if (!arrayCreateExpression.ArrayInitializer.IsNull) {
length = arrayCreateExpression.ArrayInitializer.CreateExpressions.Count;
}
Value array = Eval.NewArray((DebugType)type.GetElementType(), (uint)length, null);
if (!arrayCreateExpression.ArrayInitializer.IsNull) {
List<Expression> inits = arrayCreateExpression.ArrayInitializer.CreateExpressions;
if (inits.Count != length)
throw new EvaluateException(arrayCreateExpression, "Incorrect initializer length");
for(int i = 0; i < length; i++) {
TypedValue init = EvaluateAs(inits[i], (DebugType)type.GetElementType());
array.SetArrayElement(new int[] { i }, init.Value);
}
}
return new TypedValue(array, type);
}
public override object VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data)
{
TypedValue target;

6
src/AddIns/Misc/Debugger/Debugger.Core/Value.cs

@ -346,6 +346,12 @@ namespace Debugger @@ -346,6 +346,12 @@ namespace Debugger
return CorArrayValue.GetElement(indices);
}
public void SetArrayElement(int[] elementIndices, Value newVal)
{
Value elem = GetArrayElement(elementIndices);
elem.SetValue(newVal);
}
/// <summary> Returns all elements in the array </summary>
public Value[] GetArrayElements()
{

Loading…
Cancel
Save