Expression Evaluator Architecture

Integrating a proprietary language into the Visual Studio debug package means implementing the required expression evaluator (EE) interfaces and calling the common language run-time symbol provider (SP) and binder interfaces. The SP and binder objects, together with the current execution address, are the context in which expressions are evaluated. The information that these interfaces produce and consume represents the key concepts in the architecture of an EE.

Overview

Parsing the Expression

When you are debugging a program, expressions are evaluated for a number of reasons but always when the program being debugged has been stopped at a breakpoint (either a breakpoint placed by the user or one caused by an exception). It is at this moment when Visual Studio obtains a stack frame, as represented by the IDebugStackFrame2 interface, from the debug engine (DE). Visual Studio then calls IDebugStackFrame2::GetExpressionContext to obtain the IDebugExpressionContext2 interface. This interface represents a context in which expressions can be evaluated; IDebugExpressionContext2::ParseText is the entry point to the evaluation process. Up until this point, all interfaces are implemented by the DE.

When IDebugExpressionContext2::ParseText is called, the DE instantiates the EE associated with the language of the source file where the breakpoint occurred (the DE also instantiates the SH at this point). The EE is represented by the IDebugExpressionEvaluator interface. The DE then calls IDebugExpressionEvaluator::Parse to convert the expression (in text form) to a parsed expression, ready for evaluation. This parsed expression is represented by the IDebugParsedExpression interface. Note that the expression is typically parsed and not evaluated at this point.

The DE creates an object that implements the IDebugExpression2 interface, puts the IDebugParsedExpression object into the IDebugExpression2 object, and returns the IDebugExpression2 object from IDebugExpressionContext2::ParseText.

Evaluating the Expression

Visual Studio calls either IDebugExpression2::EvaluateSync or IDebugExpression2::EvaluateAsync to evaluate the parsed expression. Both of these methods call IDebugParsedExpression::EvaluateSync (IDebugExpression2::EvaluateSync calls the method immediately, while IDebugExpression2::EvaluateAsync calls the method through a background thread) to evaluate the parsed expression and return an IDebugProperty2 interface that represents the value and type of the parsed expression. IDebugParsedExpression::EvaluateSync uses the supplied SH, address and binder to convert the parsed expression into an actual value, represented by the IDebugProperty2 interface.

For Example

After a breakpoint is hit in a running program, the user chooses to view a variable in the QuickWatch dialog box. This dialog box shows the variable's name, its value, and its type. The user can usually change the value.

When the QuickWatch dialog box is shown, the name of the variable being examined is sent as text to IDebugExpressionContext2::ParseText. This returns an IDebugExpression2 object representing the parsed expression, in this case, the variable. IDebugExpression2::EvaluateSync is then called to produce an IDebugProperty2 object that represents the variable's value and type, as well as its name. It is this information that is displayed.

If the user changes the variable's value, IDebugProperty2::SetValueAsString is called with the new value, which changes the value of the variable in memory so it will be used when the program resumes running.

See Displaying Locals for more details on this process of displaying the values of variables. See Changing the Value of a Local for more details on how a variable's value is changed.

In This Section

See Also

Concepts

Changing the Value of a Local

Other Resources

Writing a Common Language Runtime Expression Evaluator

Displaying Locals