diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionEvaluator.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionEvaluator.cs
index 5bc870a8bf..c549bbeb5c 100644
--- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionEvaluator.cs
+++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionEvaluator.cs
@@ -8,6 +8,7 @@ using ICSharpCode.NRefactory.PrettyPrinter;
using System;
using System.Collections;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Text;
using Debugger.MetaData;
using ICSharpCode.NRefactory;
@@ -18,7 +19,7 @@ namespace Debugger
{
public class ExpressionEvaluator: NotImplementedAstVisitor
{
- /// Evaluate given expression. If you expression tree already, use overloads of this method.
+ /// Evaluate given expression. If you have expression tree already, use overloads of this method.
/// Returned value or null for statements
public static Value Evaluate(string code, SupportedLanguage language, StackFrame context)
{
@@ -45,49 +46,12 @@ namespace Debugger
}
}
- static Dictionary> expressionCache = new Dictionary>();
-
public static Value Evaluate(INode code, StackFrame context)
{
if (context == null) throw new ArgumentNullException("context");
if (context.IsInvalid) throw new DebuggerException("The context is no longer valid");
- string codeAsText = code.PrettyPrint();
-
- // Get value from cache if possible
- if (expressionCache.ContainsKey(context.AppDomain) &&
- expressionCache[context.AppDomain].ContainsKey(codeAsText)) {
- Value cached = expressionCache[context.AppDomain][codeAsText];
- if (!cached.IsInvalid) {
- if (context.Process.Options.Verbose) {
- context.Process.TraceMessage(string.Format("Cached: {0}", codeAsText));
- }
- return cached;
- }
- }
-
- Value result;
- DateTime start = Debugger.Util.HighPrecisionTimer.Now;
- try {
- result = (Value)code.AcceptVisitor(new ExpressionEvaluator(context), null);
- } catch (GetValueException) {
- throw;
- } catch (NotImplementedException e) {
- throw new GetValueException(code, "Language feature not implemented: " + e.Message);
- }
- DateTime end = Debugger.Util.HighPrecisionTimer.Now;
-
- // Store value in cache
- if (!expressionCache.ContainsKey(context.AppDomain)) {
- expressionCache[context.AppDomain] = new Dictionary();
- // TODO
- }
- // expressionCache[context.AppDomain][codeAsText] = result;
-
- if (context.Process.Options.Verbose) {
- context.Process.TraceMessage(string.Format("Evaluated: {0} ({1} ms)", code, (end - start).TotalMilliseconds));
- }
- return result;
+ return new ExpressionEvaluator(context).Evaluate(code, false);
}
public static string FormatValue(Value val)
@@ -129,6 +93,32 @@ namespace Debugger
}
}
+ public Value Evaluate(INode expression)
+ {
+ return Evaluate(expression, true);
+ }
+
+ public Value Evaluate(INode expression, bool permRef)
+ {
+ Stopwatch watch = new Stopwatch();
+ watch.Start();
+
+ Value val;
+ try {
+ val = (Value)expression.AcceptVisitor(this, null);
+ if (val != null && permRef)
+ val = val.GetPermanentReference();
+ } catch (GetValueException) {
+ throw;
+ } catch (NotImplementedException e) {
+ throw new GetValueException(expression, "Language feature not implemented: " + e.Message);
+ } finally {
+ watch.Stop();
+ context.Process.TraceMessage("Evaluated: {0} in {1} ms total", expression.PrettyPrint(), watch.ElapsedMilliseconds);
+ }
+
+ return val;
+ }
StackFrame context;
@@ -136,7 +126,7 @@ namespace Debugger
get { return context; }
}
- public ExpressionEvaluator(StackFrame context)
+ ExpressionEvaluator(StackFrame context)
{
this.context = context;
}
@@ -164,18 +154,22 @@ namespace Debugger
Value right;
if (op == BinaryOperatorType.None) {
- right = (Value)assignmentExpression.Right.AcceptVisitor(this, null);
+ right = Evaluate(assignmentExpression.Right);
} else {
BinaryOperatorExpression binOpExpr = new BinaryOperatorExpression();
binOpExpr.Left = assignmentExpression.Left;
binOpExpr.Op = op;
binOpExpr.Right = assignmentExpression.Right;
- right = (Value)VisitBinaryOperatorExpression(binOpExpr, null);
+ right = Evaluate(binOpExpr);
}
- right = right.GetPermanentReference();
- Value left = ((Value)assignmentExpression.Left.AcceptVisitor(this, null));
+ // We can not have perfRef because we need to be able to set the value
+ Value left = (Value)assignmentExpression.Left.AcceptVisitor(this, null);
+ if (left == null) {
+ // Can this happen?
+ throw new GetValueException(string.Format("\"{0}\" can not be set", assignmentExpression.Left.PrettyPrint()));
+ }
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));
}
@@ -186,7 +180,7 @@ namespace Debugger
public override object VisitBlockStatement(BlockStatement blockStatement, object data)
{
foreach(INode statement in blockStatement.Children) {
- statement.AcceptVisitor(this, null);
+ Evaluate(statement);
}
return null;
}
@@ -198,7 +192,7 @@ namespace Debugger
public override object VisitExpressionStatement(ExpressionStatement expressionStatement, object data)
{
- expressionStatement.Expression.AcceptVisitor(this, null);
+ Evaluate(expressionStatement.Expression);
return null;
}
@@ -237,11 +231,11 @@ namespace Debugger
{
List indexes = new List();
foreach(Expression indexExpr in indexerExpression.Indexes) {
- Value indexValue = ((Value)indexExpr.AcceptVisitor(this, null)).GetPermanentReference();
+ Value indexValue = Evaluate(indexExpr);
indexes.Add(indexValue);
}
- Value target = (Value)indexerExpression.TargetObject.AcceptVisitor(this, null);
+ Value target = Evaluate(indexerExpression.TargetObject);
if (target.Type.IsArray) {
List intIndexes = new List();
@@ -272,31 +266,31 @@ namespace Debugger
string methodName;
MemberReferenceExpression memberRef = invocationExpression.TargetObject as MemberReferenceExpression;
if (memberRef != null) {
- target = ((Value)memberRef.TargetObject.AcceptVisitor(this, null)).GetPermanentReference();
+ target = Evaluate(memberRef.TargetObject);
methodName = memberRef.MemberName;
} else {
IdentifierExpression ident = invocationExpression.TargetObject as IdentifierExpression;
if (ident != null) {
- target = context.GetThisValue();
+ target = Evaluate(new ThisReferenceExpression());
methodName = ident.Identifier;
} else {
throw new GetValueException("Member reference expected for method invocation");
}
}
- List args = new List();
- 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");
}
+ List args = new List();
+ foreach(Expression expr in invocationExpression.Arguments) {
+ args.Add(Evaluate(expr));
+ }
return target.InvokeMethod(method, args.ToArray());
}
public override object VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data)
{
- Value target = (Value)memberReferenceExpression.TargetObject.AcceptVisitor(this, null);
+ Value target = Evaluate(memberReferenceExpression.TargetObject);
Value member = target.GetMemberValue(memberReferenceExpression.MemberName);
if (member != null) {
return member;
@@ -307,7 +301,7 @@ namespace Debugger
public override object VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data)
{
- return parenthesizedExpression.Expression.AcceptVisitor(this, null);
+ return Evaluate(parenthesizedExpression.Expression);
}
public override object VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data)
@@ -322,12 +316,12 @@ namespace Debugger
public override object VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data)
{
- Value value = ((Value)unaryOperatorExpression.Expression.AcceptVisitor(this, null));
+ Value value = Evaluate(unaryOperatorExpression.Expression);
UnaryOperatorType op = unaryOperatorExpression.Op;
if (op == UnaryOperatorType.Dereference) {
if (!value.Type.IsPointer) throw new GetValueException("Target object is not a pointer");
- return value.Dereference();
+ return value.Dereference(); // TODO: Test
}
if (!value.Type.IsPrimitive) throw new GetValueException("Primitive value expected");
@@ -384,8 +378,8 @@ namespace Debugger
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();
+ Value left = Evaluate(binaryOperatorExpression.Left);
+ Value right = Evaluate(binaryOperatorExpression.Right);
object result = VisitBinaryOperatorExpressionInternal(left, right, binaryOperatorExpression.Op);
// Conver long to int if possible