Browse Source

Console: Pretty print ICollection

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4354 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 16 years ago
parent
commit
c8215974ff
  1. 3
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj
  2. 337
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Expressions/AstEvaluator.cs
  3. 328
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Expressions/EvaluateAstVisitor.cs
  4. 2
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Eval.cs
  5. 28
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.Object.cs
  6. 7
      src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/AstEval.cs

3
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj

@ -79,9 +79,8 @@ @@ -79,9 +79,8 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Configuration\AssemblyInfo.cs" />
<Compile Include="Src\IsBreakpointCondition.cs" />
<Compile Include="Src\Expressions\AstEvaluator.cs" />
<Compile Include="Src\Expressions\EvaluateAstVisitor.cs" />
<Compile Include="Src\IsBreakpointCondition.cs" />
<Compile Include="Src\Options\DebuggingOptions.cs" />
<Compile Include="Src\Options\DebuggingOptionsPanel.cs">
<SubType>UserControl</SubType>

337
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Expressions/AstEvaluator.cs

@ -5,13 +5,17 @@ @@ -5,13 +5,17 @@
// <version>$Revision$</version>
// </file>
using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using Debugger.MetaData;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.Visitors;
using System.Text;
namespace Debugger.AddIn
{
public static class AstEvaluator
public class AstEvaluator: NotImplementedAstVisitor
{
/// <returns> Returned value or null for statements </returns>
public static Value Evaluate(string code, SupportedLanguage language, StackFrame context)
@ -24,7 +28,7 @@ namespace Debugger.AddIn @@ -24,7 +28,7 @@ namespace Debugger.AddIn
throw new GetValueException(parser.Errors.ErrorOutput);
}
try {
EvaluateAstVisitor visitor = new EvaluateAstVisitor(context);
AstEvaluator visitor = new AstEvaluator(context);
return astRoot.AcceptVisitor(visitor, null) as Value;
} catch (NotImplementedException e) {
@ -52,11 +56,338 @@ namespace Debugger.AddIn @@ -52,11 +56,338 @@ namespace Debugger.AddIn
}
sb.Append("}");
return sb.ToString();
} else if (val.Type.GetInterface(typeof(ICollection).FullName) != null) {
StringBuilder sb = new StringBuilder();
sb.Append(val.Type.Name);
sb.Append(" {");
val = val.GetPermanentReference();
int count = (int)val.GetMemberValue("Count").PrimitiveValue;
for(int i = 0; i < count; i++) {
if (i > 0) sb.Append(", ");
PropertyInfo itemProperty = val.Type.GetProperty("Item");
// TODO: Appdomain constriant for create value
Value item = val.GetPropertyValue(itemProperty, Eval.CreateValue(val.Process, i));
sb.Append(FormatValue(item));
}
sb.Append("}");
return sb.ToString();
} else if (val.Type.IsPrimitive) {
return val.PrimitiveValue.ToString();
} else {
return val.InvokeToString();
}
}
StackFrame context;
public StackFrame Context {
get { return context; }
}
public AstEvaluator(StackFrame context)
{
this.context = context;
}
public override object VisitAssignmentExpression(AssignmentExpression assignmentExpression, object data)
{
// Calculate right first so that left does not get invalidated by its calculation
Value right = ((Value)assignmentExpression.Right.AcceptVisitor(this, null)).GetPermanentReference();
Value left = (Value)assignmentExpression.Left.AcceptVisitor(this, null);
if (!left.IsReference && left.Type.FullName != right.Type.FullName) {
throw new GetValueException(string.Format("Type {0} expected, {1} seen", left.Type.FullName, right.Type.FullName));
}
left.SetValue(right);
return right;
}
public override object VisitBlockStatement(BlockStatement blockStatement, object data)
{
foreach(INode statement in blockStatement.Children) {
statement.AcceptVisitor(this, null);
}
return null;
}
public override object VisitEmptyStatement(EmptyStatement emptyStatement, object data)
{
return null;
}
public override object VisitExpressionStatement(ExpressionStatement expressionStatement, object data)
{
expressionStatement.Expression.AcceptVisitor(this, null);
return null;
}
public override object VisitIdentifierExpression(IdentifierExpression identifierExpression, object data)
{
string identifier = identifierExpression.Identifier;
Value arg = context.GetArgumentValue(identifier);
if (arg != null) return arg;
Value local = context.GetLocalVariableValue(identifier);
if (local != null) return local;
if (!context.MethodInfo.IsStatic) {
Value member = context.GetThisValue().GetMemberValue(identifier);
if (member != null) return member;
} else {
MemberInfo memberInfo = context.MethodInfo.DeclaringType.GetMember(identifier);
if (memberInfo != null && memberInfo.IsStatic) {
return Value.GetMemberValue(null, memberInfo, null);
}
}
throw new GetValueException("Identifier \"" + identifier + "\" not found in this context");
}
public override object VisitIndexerExpression(IndexerExpression indexerExpression, object data)
{
List<Value> indexes = new List<Value>();
foreach(Expression indexExpr in indexerExpression.Indexes) {
Value indexValue = ((Value)indexExpr.AcceptVisitor(this, null)).GetPermanentReference();
indexes.Add(indexValue);
}
Value target = (Value)indexerExpression.TargetObject.AcceptVisitor(this, null);
if (target.Type.IsArray) {
List<int> intIndexes = new List<int>();
foreach(Value index in indexes) {
if (!index.Type.IsInteger) throw new GetValueException("Integer expected for indexer");
intIndexes.Add((int)index.PrimitiveValue);
}
return target.GetArrayElement(intIndexes.ToArray());
}
PropertyInfo pi = target.Type.GetProperty("Item");
if (pi == null) throw new GetValueException("The object does not have an indexer property");
return target.GetPropertyValue(pi, indexes.ToArray());
}
public override object VisitInvocationExpression(InvocationExpression invocationExpression, object data)
{
Value target;
string methodName;
MemberReferenceExpression memberRef = invocationExpression.TargetObject as MemberReferenceExpression;
if (memberRef != null) {
target = ((Value)memberRef.TargetObject.AcceptVisitor(this, null)).GetPermanentReference();
methodName = memberRef.MemberName;
} else {
IdentifierExpression ident = invocationExpression.TargetObject as IdentifierExpression;
if (ident != null) {
target = context.GetThisValue();
methodName = ident.Identifier;
} else {
throw new GetValueException("Member reference expected for method invocation");
}
}
List<Value> args = new List<Value>();
foreach(Expression expr in invocationExpression.Arguments) {
args.Add(((Value)expr.AcceptVisitor(this, null)).GetPermanentReference());
}
MethodInfo method = target.Type.GetMember(methodName, BindingFlags.Method | BindingFlags.IncludeSuperType) as MethodInfo;
if (method == null) {
throw new GetValueException("Method " + methodName + " not found");
}
return target.InvokeMethod(method, args.ToArray());
}
public override object VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data)
{
Value target = (Value)memberReferenceExpression.TargetObject.AcceptVisitor(this, null);
Value member = target.GetMemberValue(memberReferenceExpression.MemberName);
if (member != null) {
return member;
} else {
throw new GetValueException("Member \"" + memberReferenceExpression.MemberName + "\" not found");
}
}
public override object VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data)
{
return parenthesizedExpression.Expression.AcceptVisitor(this, null);
}
public override object VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data)
{
return Eval.CreateValue(context.Process, primitiveExpression.Value);
}
public override object VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression, object data)
{
return context.GetThisValue();
}
public override object VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data)
{
Value left = ((Value)binaryOperatorExpression.Left.AcceptVisitor(this, null)).GetPermanentReference();
Value right = ((Value)binaryOperatorExpression.Right.AcceptVisitor(this, null)).GetPermanentReference();
object result = VisitBinaryOperatorExpressionInternal(left, right, binaryOperatorExpression.Op);
// Conver long to int if possible
if (result is long && int.MinValue <= (long)result && (long)result <= int.MaxValue) result = (int)(long)result;
return Eval.CreateValue(context.Process, result);
}
public object VisitBinaryOperatorExpressionInternal(Value leftValue, Value rightValue, BinaryOperatorType op)
{
object left = leftValue.Type.IsPrimitive ? leftValue.PrimitiveValue : null;
object right = rightValue.Type.IsPrimitive ? rightValue.PrimitiveValue : null;
// Both are classes - do reference comparison
if (left == null && right == null) {
if (leftValue.IsNull || rightValue.IsNull) {
return leftValue.IsNull && rightValue.IsNull;
} else {
// TODO: Make sure this works for byrefs and arrays
return leftValue.Address == rightValue.Address;
}
}
if (left == null && right != null) {
throw new GetValueException("The left side of binary operation is not primitive value");
}
if (left != null && right == null) {
throw new GetValueException("The right side of binary operation is not primitive value");
}
// Both are primitive - do value the operation
if (left != null && right != null) {
try {
// Note the order of these tests is significant (eg "5" + 6: "56" or 11?)
// String operation
if (left is string || right is string) {
string a = Convert.ToString(left);
string b = Convert.ToString(right);
switch (op) {
case BinaryOperatorType.Equality: return a == b;
case BinaryOperatorType.InEquality: return a != b;
case BinaryOperatorType.Add: return a + b;
case BinaryOperatorType.ReferenceEquality: return a == b;
case BinaryOperatorType.ReferenceInequality: return a != b;
case BinaryOperatorType.NullCoalescing: return a ?? b;
}
}
// Bool operation
if (left is bool || right is bool) {
bool a = Convert.ToBoolean(left);
bool b = Convert.ToBoolean(right);
switch (op) {
case BinaryOperatorType.BitwiseAnd: return a & b;
case BinaryOperatorType.BitwiseOr: return a | b;
case BinaryOperatorType.LogicalAnd: return a && b;
case BinaryOperatorType.LogicalOr: return a || b;
case BinaryOperatorType.ExclusiveOr: return a ^ b;
case BinaryOperatorType.Equality: return a == b;
case BinaryOperatorType.InEquality: return a != b;
case BinaryOperatorType.ReferenceEquality: return a == b;
case BinaryOperatorType.ReferenceInequality: return a != b;
}
}
// Float operation
if (left is double || left is float || right is double || right is float) {
double a = Convert.ToDouble(left);
double b = Convert.ToDouble(right);
switch (op) {
case BinaryOperatorType.GreaterThan: return a > b;
case BinaryOperatorType.GreaterThanOrEqual: return a >= b;
case BinaryOperatorType.Equality: return a == b;
case BinaryOperatorType.InEquality: return a != b;
case BinaryOperatorType.LessThan: return a < b;
case BinaryOperatorType.LessThanOrEqual: return a <= b;
case BinaryOperatorType.Add: return a + b;
case BinaryOperatorType.Subtract: return a - b;
case BinaryOperatorType.Multiply: return a * b;
case BinaryOperatorType.Divide: return a / b;
case BinaryOperatorType.Modulus: return a % b;
case BinaryOperatorType.Concat: return a + b;
case BinaryOperatorType.ReferenceEquality: return a == b;
case BinaryOperatorType.ReferenceInequality: return a != b;
}
}
// Integer operation
if (left is byte || left is sbyte || left is int || left is uint || left is long || left is ulong ||
right is byte || right is sbyte || right is int || right is uint || right is long || right is ulong) {
long a = Convert.ToInt64(left);
long b = Convert.ToInt64(right);
switch (op) {
case BinaryOperatorType.BitwiseAnd: return a & b;
case BinaryOperatorType.BitwiseOr: return a | b;
case BinaryOperatorType.ExclusiveOr: return a ^ b;
case BinaryOperatorType.GreaterThan: return a > b;
case BinaryOperatorType.GreaterThanOrEqual: return a >= b;
case BinaryOperatorType.Equality: return a == b;
case BinaryOperatorType.InEquality: return a != b;
case BinaryOperatorType.LessThan: return a < b;
case BinaryOperatorType.LessThanOrEqual: return a <= b;
case BinaryOperatorType.Add: return a + b;
case BinaryOperatorType.Subtract: return a - b;
case BinaryOperatorType.Multiply: return a * b;
case BinaryOperatorType.Divide: return a / b;
case BinaryOperatorType.Modulus: return a % b;
case BinaryOperatorType.Concat: return a + b;
case BinaryOperatorType.ShiftLeft: return a << Convert.ToInt32(b);
case BinaryOperatorType.ShiftRight: return a >> Convert.ToInt32(b);
case BinaryOperatorType.ReferenceEquality: return a == b;
case BinaryOperatorType.ReferenceInequality: return a != b;
}
}
// Char operation
if (left is char || right is char) {
char a = Convert.ToChar(left);
char b = Convert.ToChar(right);
switch (op) {
case BinaryOperatorType.BitwiseAnd: return a & b;
case BinaryOperatorType.BitwiseOr: return a | b;
case BinaryOperatorType.ExclusiveOr: return a ^ b;
case BinaryOperatorType.GreaterThan: return a > b;
case BinaryOperatorType.GreaterThanOrEqual: return a >= b;
case BinaryOperatorType.Equality: return a == b;
case BinaryOperatorType.InEquality: return a != b;
case BinaryOperatorType.LessThan: return a < b;
case BinaryOperatorType.LessThanOrEqual: return a <= b;
case BinaryOperatorType.Add: return a + b;
case BinaryOperatorType.Subtract: return a - b;
case BinaryOperatorType.Multiply: return a * b;
case BinaryOperatorType.Divide: return a / b;
case BinaryOperatorType.Modulus: return a % b;
case BinaryOperatorType.Concat: return a + b;
case BinaryOperatorType.ShiftLeft: return a << b;
case BinaryOperatorType.ShiftRight: return a >> b;
case BinaryOperatorType.ReferenceEquality: return a == b;
case BinaryOperatorType.ReferenceInequality: return a != b;
}
}
} catch(FormatException e) {
throw new GetValueException("Conversion error: " + e.Message);
} catch(InvalidCastException e) {
throw new GetValueException("Conversion error: " + e.Message);
} catch(OverflowException e) {
throw new GetValueException("Conversion error: " + e.Message);
}
}
throw new DebuggerException("Unreachable code");
}
}
}

328
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Expressions/EvaluateAstVisitor.cs

@ -1,328 +0,0 @@ @@ -1,328 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using ICSharpCode.NRefactory.Visitors;
using System;
using System.Collections.Generic;
using Debugger.MetaData;
using ICSharpCode.NRefactory.Ast;
namespace Debugger.AddIn
{
public class EvaluateAstVisitor: NotImplementedAstVisitor
{
StackFrame context;
public StackFrame Context {
get { return context; }
}
public EvaluateAstVisitor(StackFrame context)
{
this.context = context;
}
public override object VisitAssignmentExpression(AssignmentExpression assignmentExpression, object data)
{
// Calculate right first so that left does not get invalidated by its calculation
Value right = ((Value)assignmentExpression.Right.AcceptVisitor(this, null)).GetPermanentReference();
Value left = (Value)assignmentExpression.Left.AcceptVisitor(this, null);
if (!left.IsReference && left.Type.FullName != right.Type.FullName) {
throw new GetValueException(string.Format("Type {0} expected, {1} seen", left.Type.FullName, right.Type.FullName));
}
left.SetValue(right);
return right;
}
public override object VisitBlockStatement(BlockStatement blockStatement, object data)
{
foreach(INode statement in blockStatement.Children) {
statement.AcceptVisitor(this, null);
}
return null;
}
public override object VisitEmptyStatement(EmptyStatement emptyStatement, object data)
{
return null;
}
public override object VisitExpressionStatement(ExpressionStatement expressionStatement, object data)
{
expressionStatement.Expression.AcceptVisitor(this, null);
return null;
}
public override object VisitIdentifierExpression(IdentifierExpression identifierExpression, object data)
{
string identifier = identifierExpression.Identifier;
Value arg = context.GetArgumentValue(identifier);
if (arg != null) return arg;
Value local = context.GetLocalVariableValue(identifier);
if (local != null) return local;
if (!context.MethodInfo.IsStatic) {
Value member = context.GetThisValue().GetMemberValue(identifier);
if (member != null) return member;
} else {
MemberInfo memberInfo = context.MethodInfo.DeclaringType.GetMember(identifier);
if (memberInfo != null && memberInfo.IsStatic) {
return Value.GetMemberValue(null, memberInfo, null);
}
}
throw new GetValueException("Identifier \"" + identifier + "\" not found in this context");
}
public override object VisitIndexerExpression(IndexerExpression indexerExpression, object data)
{
List<Value> indexes = new List<Value>();
foreach(Expression indexExpr in indexerExpression.Indexes) {
Value indexValue = ((Value)indexExpr.AcceptVisitor(this, null)).GetPermanentReference();
indexes.Add(indexValue);
}
Value target = (Value)indexerExpression.TargetObject.AcceptVisitor(this, null);
if (target.Type.IsArray) {
List<int> intIndexes = new List<int>();
foreach(Value index in indexes) {
if (!index.Type.IsInteger) throw new GetValueException("Integer expected for indexer");
intIndexes.Add((int)index.PrimitiveValue);
}
return target.GetArrayElement(intIndexes.ToArray());
}
PropertyInfo pi = target.Type.GetProperty("Item");
if (pi == null) throw new GetValueException("The object does not have an indexer property");
return target.GetPropertyValue(pi, indexes.ToArray());
}
public override object VisitInvocationExpression(InvocationExpression invocationExpression, object data)
{
Value target;
string methodName;
MemberReferenceExpression memberRef = invocationExpression.TargetObject as MemberReferenceExpression;
if (memberRef != null) {
target = ((Value)memberRef.TargetObject.AcceptVisitor(this, null)).GetPermanentReference();
methodName = memberRef.MemberName;
} else {
IdentifierExpression ident = invocationExpression.TargetObject as IdentifierExpression;
if (ident != null) {
target = context.GetThisValue();
methodName = ident.Identifier;
} else {
throw new GetValueException("Member reference expected for method invocation");
}
}
List<Value> args = new List<Value>();
foreach(Expression expr in invocationExpression.Arguments) {
args.Add(((Value)expr.AcceptVisitor(this, null)).GetPermanentReference());
}
MethodInfo method = target.Type.GetMember(methodName, BindingFlags.Method | BindingFlags.IncludeSuperType) as MethodInfo;
if (method == null) {
throw new GetValueException("Method " + methodName + " not found");
}
return target.InvokeMethod(method, args.ToArray());
}
public override object VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data)
{
Value target = (Value)memberReferenceExpression.TargetObject.AcceptVisitor(this, null);
Value member = target.GetMemberValue(memberReferenceExpression.MemberName);
if (member != null) {
return member;
} else {
throw new GetValueException("Member \"" + memberReferenceExpression.MemberName + "\" not found");
}
}
public override object VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data)
{
return parenthesizedExpression.Expression.AcceptVisitor(this, null);
}
public override object VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data)
{
return Eval.CreateValue(context.Process, primitiveExpression.Value);
}
public override object VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression, object data)
{
return context.GetThisValue();
}
public override object VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data)
{
Value left = ((Value)binaryOperatorExpression.Left.AcceptVisitor(this, null)).GetPermanentReference();
Value right = ((Value)binaryOperatorExpression.Right.AcceptVisitor(this, null)).GetPermanentReference();
object result = VisitBinaryOperatorExpressionInternal(left, right, binaryOperatorExpression.Op);
// Conver long to int if possible
if (result is long && int.MinValue <= (long)result && (long)result <= int.MaxValue) result = (int)(long)result;
return Eval.CreateValue(context.Process, result);
}
public object VisitBinaryOperatorExpressionInternal(Value leftValue, Value rightValue, BinaryOperatorType op)
{
object left = leftValue.Type.IsPrimitive ? leftValue.PrimitiveValue : null;
object right = rightValue.Type.IsPrimitive ? rightValue.PrimitiveValue : null;
// Both are classes - do reference comparison
if (left == null && right == null) {
if (leftValue.IsNull || rightValue.IsNull) {
return leftValue.IsNull && rightValue.IsNull;
} else {
// TODO: Make sure this works for byrefs and arrays
return leftValue.Address == rightValue.Address;
}
}
if (left == null && right != null) {
throw new GetValueException("The left side of binary operation is not primitive value");
}
if (left != null && right == null) {
throw new GetValueException("The right side of binary operation is not primitive value");
}
// Both are primitive - do value the operation
if (left != null && right != null) {
try {
// Note the order of these tests is significant (eg "5" + 6: "56" or 11?)
// String operation
if (left is string || right is string) {
string a = Convert.ToString(left);
string b = Convert.ToString(right);
switch (op) {
case BinaryOperatorType.Equality: return a == b;
case BinaryOperatorType.InEquality: return a != b;
case BinaryOperatorType.Add: return a + b;
case BinaryOperatorType.ReferenceEquality: return a == b;
case BinaryOperatorType.ReferenceInequality: return a != b;
case BinaryOperatorType.NullCoalescing: return a ?? b;
}
}
// Bool operation
if (left is bool || right is bool) {
bool a = Convert.ToBoolean(left);
bool b = Convert.ToBoolean(right);
switch (op) {
case BinaryOperatorType.BitwiseAnd: return a & b;
case BinaryOperatorType.BitwiseOr: return a | b;
case BinaryOperatorType.LogicalAnd: return a && b;
case BinaryOperatorType.LogicalOr: return a || b;
case BinaryOperatorType.ExclusiveOr: return a ^ b;
case BinaryOperatorType.Equality: return a == b;
case BinaryOperatorType.InEquality: return a != b;
case BinaryOperatorType.ReferenceEquality: return a == b;
case BinaryOperatorType.ReferenceInequality: return a != b;
}
}
// Float operation
if (left is double || left is float || right is double || right is float) {
double a = Convert.ToDouble(left);
double b = Convert.ToDouble(right);
switch (op) {
case BinaryOperatorType.GreaterThan: return a > b;
case BinaryOperatorType.GreaterThanOrEqual: return a >= b;
case BinaryOperatorType.Equality: return a == b;
case BinaryOperatorType.InEquality: return a != b;
case BinaryOperatorType.LessThan: return a < b;
case BinaryOperatorType.LessThanOrEqual: return a <= b;
case BinaryOperatorType.Add: return a + b;
case BinaryOperatorType.Subtract: return a - b;
case BinaryOperatorType.Multiply: return a * b;
case BinaryOperatorType.Divide: return a / b;
case BinaryOperatorType.Modulus: return a % b;
case BinaryOperatorType.Concat: return a + b;
case BinaryOperatorType.ReferenceEquality: return a == b;
case BinaryOperatorType.ReferenceInequality: return a != b;
}
}
// Integer operation
if (left is byte || left is sbyte || left is int || left is uint || left is long || left is ulong ||
right is byte || right is sbyte || right is int || right is uint || right is long || right is ulong) {
long a = Convert.ToInt64(left);
long b = Convert.ToInt64(right);
switch (op) {
case BinaryOperatorType.BitwiseAnd: return a & b;
case BinaryOperatorType.BitwiseOr: return a | b;
case BinaryOperatorType.ExclusiveOr: return a ^ b;
case BinaryOperatorType.GreaterThan: return a > b;
case BinaryOperatorType.GreaterThanOrEqual: return a >= b;
case BinaryOperatorType.Equality: return a == b;
case BinaryOperatorType.InEquality: return a != b;
case BinaryOperatorType.LessThan: return a < b;
case BinaryOperatorType.LessThanOrEqual: return a <= b;
case BinaryOperatorType.Add: return a + b;
case BinaryOperatorType.Subtract: return a - b;
case BinaryOperatorType.Multiply: return a * b;
case BinaryOperatorType.Divide: return a / b;
case BinaryOperatorType.Modulus: return a % b;
case BinaryOperatorType.Concat: return a + b;
case BinaryOperatorType.ShiftLeft: return a << Convert.ToInt32(b);
case BinaryOperatorType.ShiftRight: return a >> Convert.ToInt32(b);
case BinaryOperatorType.ReferenceEquality: return a == b;
case BinaryOperatorType.ReferenceInequality: return a != b;
}
}
// Char operation
if (left is char || right is char) {
char a = Convert.ToChar(left);
char b = Convert.ToChar(right);
switch (op) {
case BinaryOperatorType.BitwiseAnd: return a & b;
case BinaryOperatorType.BitwiseOr: return a | b;
case BinaryOperatorType.ExclusiveOr: return a ^ b;
case BinaryOperatorType.GreaterThan: return a > b;
case BinaryOperatorType.GreaterThanOrEqual: return a >= b;
case BinaryOperatorType.Equality: return a == b;
case BinaryOperatorType.InEquality: return a != b;
case BinaryOperatorType.LessThan: return a < b;
case BinaryOperatorType.LessThanOrEqual: return a <= b;
case BinaryOperatorType.Add: return a + b;
case BinaryOperatorType.Subtract: return a - b;
case BinaryOperatorType.Multiply: return a * b;
case BinaryOperatorType.Divide: return a / b;
case BinaryOperatorType.Modulus: return a % b;
case BinaryOperatorType.Concat: return a + b;
case BinaryOperatorType.ShiftLeft: return a << b;
case BinaryOperatorType.ShiftRight: return a >> b;
case BinaryOperatorType.ReferenceEquality: return a == b;
case BinaryOperatorType.ReferenceInequality: return a != b;
}
}
} catch(FormatException e) {
throw new GetValueException("Conversion error: " + e.Message);
} catch(InvalidCastException e) {
throw new GetValueException("Conversion error: " + e.Message);
} catch(OverflowException e) {
throw new GetValueException("Conversion error: " + e.Message);
}
}
throw new DebuggerException("Unreachable code");
}
}
}

2
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Eval.cs

@ -55,7 +55,7 @@ namespace Debugger @@ -55,7 +55,7 @@ namespace Debugger
case EvalState.Evaluating: throw new GetValueException("Evaluating...");
case EvalState.EvaluatedSuccessfully: return result;
case EvalState.EvaluatedException: return result;
case EvalState.EvaluatedNoResult: throw new GetValueException("No return value");
case EvalState.EvaluatedNoResult: return null;
case EvalState.EvaluatedTimeOut: throw new GetValueException("Timeout");
default: throw new DebuggerException("Unknown state");
}

28
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.Object.cs

@ -56,13 +56,7 @@ namespace Debugger @@ -56,13 +56,7 @@ namespace Debugger
#region Convenience overload methods
/// <summary> Get the value of given member. </summary>
public Value GetMemberValue(MemberInfo memberInfo)
{
return GetMemberValue(this, memberInfo, null);
}
/// <summary> Get the value of given member. </summary>
public Value GetMemberValue(MemberInfo memberInfo, Value[] arguments)
public Value GetMemberValue(MemberInfo memberInfo, params Value[] arguments)
{
return GetMemberValue(this, memberInfo, arguments);
}
@ -71,9 +65,8 @@ namespace Debugger @@ -71,9 +65,8 @@ namespace Debugger
/// <summary> Get the value of given member. </summary>
/// <param name="objectInstance">null if member is static</param>
public static Value GetMemberValue(Value objectInstance, MemberInfo memberInfo, Value[] arguments)
public static Value GetMemberValue(Value objectInstance, MemberInfo memberInfo, params Value[] arguments)
{
arguments = arguments ?? new Value[0];
if (memberInfo is FieldInfo) {
if (arguments.Length > 0) throw new GetValueException("Arguments can not be used for a field");
return GetFieldValue(objectInstance, (FieldInfo)memberInfo);
@ -135,32 +128,19 @@ namespace Debugger @@ -135,32 +128,19 @@ namespace Debugger
#region Convenience overload methods
/// <summary> Get the value of the property using the get accessor </summary>
public Value GetPropertyValue(PropertyInfo propertyInfo)
{
return GetPropertyValue(this, propertyInfo, null);
}
/// <summary> Get the value of the property using the get accessor </summary>
public Value GetPropertyValue(PropertyInfo propertyInfo, Value[] arguments)
public Value GetPropertyValue(PropertyInfo propertyInfo, params Value[] arguments)
{
return GetPropertyValue(this, propertyInfo, arguments);
}
/// <summary> Get the value of the property using the get accessor </summary>
public static Value GetPropertyValue(Value objectInstance, PropertyInfo propertyInfo)
{
return GetPropertyValue(objectInstance, propertyInfo, null);
}
#endregion
/// <summary> Get the value of the property using the get accessor </summary>
public static Value GetPropertyValue(Value objectInstance, PropertyInfo propertyInfo, Value[] arguments)
public static Value GetPropertyValue(Value objectInstance, PropertyInfo propertyInfo, params Value[] arguments)
{
CheckObject(objectInstance, propertyInfo);
if (propertyInfo.GetMethod == null) throw new GetValueException("Property does not have a get method");
arguments = arguments ?? new Value[0];
Expression objectInstanceExpression = objectInstance != null ? objectInstance.Expression : new EmptyExpression();

7
src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/AstEval.cs

@ -69,6 +69,9 @@ namespace Debugger.Tests { @@ -69,6 +69,9 @@ namespace Debugger.Tests {
Eval("list[1]");
Eval("list[i]");
Eval("list.Add(42); list.Add(52);");
Eval("list");
EndTest();
}
@ -117,9 +120,11 @@ namespace Debugger.Tests { @@ -117,9 +120,11 @@ namespace Debugger.Tests {
<Eval> array[1] = e </Eval>
<Eval> array[i] = o </Eval>
<Eval> array[i - 1] = l </Eval>
<Eval> list = System.Collections.Generic.List`1[System.Char] </Eval>
<Eval> list = List&lt;Char&gt; {H, e, l, l, o} </Eval>
<Eval> list[1] = e </Eval>
<Eval> list[i] = o </Eval>
<Eval> list.Add(42); list.Add(52); = </Eval>
<Eval> list = List&lt;Char&gt; {H, e, l, l, o, *, 4} </Eval>
<ProcessExited />
</Test>
</DebuggerTests>

Loading…
Cancel
Save