diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Expressions/AstEvaluator.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Expressions/AstEvaluator.cs
index b8a50c2cba..a4c61e2b86 100644
--- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Expressions/AstEvaluator.cs
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Expressions/AstEvaluator.cs
@@ -52,6 +52,8 @@ namespace Debugger.AddIn
}
sb.Append("}");
return sb.ToString();
+ } else if (val.Type.IsPrimitive) {
+ return val.PrimitiveValue.ToString();
} else {
return val.InvokeToString();
}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Expressions/EvaluateAstVisitor.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Expressions/EvaluateAstVisitor.cs
index 4971429a7d..32c0368f57 100644
--- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Expressions/EvaluateAstVisitor.cs
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Expressions/EvaluateAstVisitor.cs
@@ -149,15 +149,7 @@ namespace Debugger.AddIn
public override object VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data)
{
- if (primitiveExpression.Value == null) {
- return Eval.CreateValue(context.Process, null);
- } else if (primitiveExpression.Value is string) {
- return Eval.NewString(context.Process, primitiveExpression.Value as string);
- } else {
- Value val = Eval.NewObjectNoConstructor(DebugType.Create(context.Process, null, primitiveExpression.Value.GetType().FullName));
- val.PrimitiveValue = primitiveExpression.Value;
- return val;
- }
+ return Eval.CreateValue(context.Process, primitiveExpression.Value);
}
public override object VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression, object data)
@@ -170,41 +162,167 @@ namespace Debugger.AddIn
Value left = ((Value)binaryOperatorExpression.Left.AcceptVisitor(this, null)).GetPermanentReference();
Value right = ((Value)binaryOperatorExpression.Right.AcceptVisitor(this, null)).GetPermanentReference();
- 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));
+ 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;
+ }
}
- Value val = Eval.NewObjectNoConstructor(DebugType.Create(context.Process, null, typeof(bool).FullName));
+ 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");
+ }
- try {
- switch (binaryOperatorExpression.Op)
- {
- case BinaryOperatorType.Equality :
- val.PrimitiveValue = Equals(right.PrimitiveValue, left.PrimitiveValue);
- break;
- case BinaryOperatorType.InEquality :
- val.PrimitiveValue = !Equals(right.PrimitiveValue, left.PrimitiveValue);
- break;
-// case BinaryOperatorType.Add :
-// val.PrimitiveValue = (right.PrimitiveValue.ToString() + left.PrimitiveValue.ToString());
-// break;
-// case BinaryOperatorType.GreaterThan :
-// val.PrimitiveValue = (right.PrimitiveValue > left.PrimitiveValue);
-// break;
-// case BinaryOperatorType.LessThanOrEqual :
-// val.PrimitiveValue = (right.PrimitiveValue <= left.PrimitiveValue);
-// break;
-// case BinaryOperatorType.GreaterThanOrEqual :
-// val.PrimitiveValue = (right.PrimitiveValue >= left.PrimitiveValue);
-// break;
- default:
- throw new NotImplementedException("BinaryOperator: " + binaryOperatorExpression.Op);
+ // 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);
}
- } catch (System.Exception e) {
- throw new GetValueException(e.Message);
}
- return val;
+ throw new DebuggerException("Unreachable code");
}
}
}
diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Eval.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Eval.cs
index d7c1ee71f0..0c67f9a2d3 100644
--- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Eval.cs
+++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Eval.cs
@@ -258,7 +258,25 @@ namespace Debugger
(uint)corArgs.Count, corArgs.ToArray()
);
}
+
+ public static Value CreateValue(Process process, object value)
+ {
+ if (value == null) {
+ ICorDebugClass corClass = DebugType.Create(process, null, typeof(object).FullName).CorType.Class;
+ ICorDebugEval corEval = CreateCorEval(process);
+ ICorDebugValue corValue = corEval.CreateValue((uint)CorElementType.CLASS, corClass);
+ return new Value(process, new Expressions.PrimitiveExpression(value), corValue);
+ } else if (value is string) {
+ return Eval.NewString(process, (string)value);
+ } else {
+ // TODO: Check if it is primitive type
+ Value val = Eval.NewObjectNoConstructor(DebugType.Create(process, null, value.GetType().FullName));
+ val.PrimitiveValue = value;
+ return val;
+ }
+ }
+ /*
// The following function create values only for the purpuse of evalutaion
// They actually do not allocate memory on the managed heap
// The advantage is that it does not continue the process
@@ -282,6 +300,7 @@ namespace Debugger
}
return v;
}
+ */
#region Convenience methods
diff --git a/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/AstEval.cs b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/AstEval.cs
index 872929a76e..801939ec0f 100644
--- a/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/AstEval.cs
+++ b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/AstEval.cs
@@ -14,7 +14,10 @@ namespace Debugger.Tests.TestPrograms
{
public static void Main()
{
- int index = 4;
+ byte b = 1;
+ int i = 4;
+ float pi = 3.14f;
+ string hi = "hi";
char[] array = "Hello".ToCharArray();
char[] array2 = "world".ToCharArray();
@@ -39,14 +42,32 @@ namespace Debugger.Tests {
{
StartTest("AstEval.cs");
+ Eval("b");
+ Eval("i");
+ Eval("pi");
+ Eval("pi - 3");
+ Eval("b + i");
+ Eval("i + b");
+ Eval("b + pi");
+ Eval("pi + b");
+ Eval("hi + pi");
+ Eval("pi + hi");
+ Eval("pi + \" \" + hi");
+
+ Eval("(5 + 6) % (1 + 2)");
+ Eval("b + 3 == i");
+ Eval("b + 4 == i");
+ Eval("true == true");
+ Eval("true == false");
+
Eval("array");
Eval("arrays");
Eval("array[1]");
- Eval("array[index]");
- Eval("array[index - 1]");
+ Eval("array[i]");
+ Eval("array[i - 1]");
Eval("list");
Eval("list[1]");
- Eval("list[index]");
+ Eval("list[i]");
EndTest();
}
@@ -74,15 +95,31 @@ namespace Debugger.Tests {
mscorlib.dll (No symbols)
AstEval.exe (Has symbols)
- Break AstEval.cs:24,4-24,40
+ Break AstEval.cs:27,4-27,40
+ b = 1
+ i = 4
+ pi = 3.14
+ pi - 3 = 0.140000104904175
+ b + i = 5
+ i + b = 5
+ b + pi = 4.14000010490417
+ pi + b = 4.14000010490417
+ hi + pi = hi3.14
+ pi + hi = 3.14hi
+ pi + " " + hi = 3.14 hi
+ (5 + 6) % (1 + 2) = 2
+ b + 3 == i = True
+ b + 4 == i = False
+ true == true = True
+ true == false = False
array = Char[] {H, e, l, l, o}
arrays = Char[][] {Char[] {H, e, l, l, o}, Char[] {w, o, r, l, d}}
array[1] = e
- array[index] = o
- array[index - 1] = Error: BinaryOperator: Subtract
+ array[i] = o
+ array[i - 1] = l
list = System.Collections.Generic.List`1[System.Char]
list[1] = e
- list[index] = o
+ list[i] = o