Debugger: Rework expression parsing API.

ExpressionInfo:
- No longer stores an explicit result type (this is inferred from
  evaluation of the expression itself now).
- Introduce class ExpressionResult for returning the result of an
  expression computation. This can currently take the form of either
  a primitive value, or a value node object.
- Adjust UserInterfaceListener and ExpressionInfo::Listener to take
  the above changes into account, and correspondingly adjust all
  callers/listeners.

CLanguageExpressionEvaluator:
- Introduce child class Operand. This subsumes the functionality that
  was previously in the separate Number class, and can represent a
  primitive value, a value node or  a type. Also has functionality to
  implicity handle type promotion/inferring when performing calculations
  between operands.
- Adjust expression parser to operate in terms of Operands rather than
  Numbers. This allows a number of improvements, most notably that an
  expression can now return a value node as a result rather than only
  a primitive number. This capability isn't yet fully used, but paves
  the way for future uses such as an expression that evaluates to a data
  member, a global variable, or an arbitrary pointer of a particular type.
- Various cleanups/simplifications that were possible as a result of the above
  changes.

ExpressionEvaluationWindow/ExpressionPromptWindow:
- Remove type menu field, since the expression API no longer uses it.

Adding/removing expressions in the VariablesView is temporarily disabled,
pending some further rework there to properly handle the new result object.
This commit is contained in:
Rene Gollent 2014-11-15 00:31:17 -05:00
parent 8d48eb9311
commit 81c848a14a
29 changed files with 1682 additions and 1630 deletions

View File

@ -222,7 +222,6 @@ Application Debugger :
# types
ArrayIndexPath.cpp
Number.cpp
TargetAddressRangeList.cpp
ValueLocation.cpp

View File

@ -35,6 +35,7 @@
#include "Team.h"
#include "Tracing.h"
#include "Value.h"
#include "ValueLocation.h"
#include "Worker.h"
@ -63,7 +64,7 @@ public:
}
virtual void ExpressionEvaluated(ExpressionInfo* info, status_t result,
Value* value)
ExpressionResult* value)
{
fHandler->_HandleBreakpointConditionEvaluated(value);
}
@ -888,14 +889,8 @@ ThreadHandler::_HandleBreakpointConditionIfNeeded(CpuState* cpuState)
if (listener == NULL)
return false;
Type* type = new(std::nothrow) SyntheticPrimitiveType(B_UINT64_TYPE);
if (type == NULL)
return false;
BReference<Type> typeReference(type, true);
ExpressionInfo* expressionInfo = new(std::nothrow) ExpressionInfo(
userBreakpoint->Condition(), type);
userBreakpoint->Condition());
if (expressionInfo == NULL)
return false;
@ -921,23 +916,13 @@ ThreadHandler::_HandleBreakpointConditionIfNeeded(CpuState* cpuState)
teamLocker.Lock();
bool stop = false;
if (fConditionResult == NULL)
stop = true;
else {
BVariant value;
if (!fConditionResult->ToVariant(value))
stop = true;
if (!value.TypeIsInteger(value.Type()))
stop = true;
stop = value.ToBool();
fConditionResult->ReleaseReference();
fConditionResult = NULL;
}
if (stop)
if (_CheckStopCondition()) {
if (fConditionResult != NULL) {
fConditionResult->ReleaseReference();
fConditionResult = NULL;
}
return false;
else {
} else {
_SetThreadState(THREAD_STATE_RUNNING, NULL,
THREAD_STOPPED_UNKNOWN, BString());
fDebuggerInterface->ContinueThread(fThread->ID());
@ -951,7 +936,7 @@ ThreadHandler::_HandleBreakpointConditionIfNeeded(CpuState* cpuState)
void
ThreadHandler::_HandleBreakpointConditionEvaluated(Value* value)
ThreadHandler::_HandleBreakpointConditionEvaluated(ExpressionResult* value)
{
fConditionResult = value;
if (fConditionResult != NULL)
@ -960,6 +945,25 @@ ThreadHandler::_HandleBreakpointConditionEvaluated(Value* value)
}
bool
ThreadHandler::_CheckStopCondition()
{
// if we we're unable to properly assess the expression result
// in any way, fall back to behaving like an unconditional breakpoint.
if (fConditionResult == NULL)
return true;
if (fConditionResult->Kind() != EXPRESSION_RESULT_KIND_PRIMITIVE)
return true;
BVariant value;
if (!fConditionResult->PrimitiveValue()->ToVariant(value))
return true;
return value.ToBool();
}
bool
ThreadHandler::_HasExitedFrame(target_addr_t framePointer) const
{

View File

@ -18,10 +18,10 @@
class BreakpointManager;
class DebuggerInterface;
class ExpressionResult;
class ImageDebugInfoJobListener;
class StackFrame;
class Statement;
class Value;
class Worker;
@ -102,7 +102,8 @@ private:
bool _HandleBreakpointConditionIfNeeded(
CpuState* cpuState);
void _HandleBreakpointConditionEvaluated(
Value* value);
ExpressionResult* value);
bool _CheckStopCondition();
bool _HandleBreakpointHitStep(CpuState* cpuState);
bool _HandleSingleStepStep(CpuState* cpuState);
@ -124,7 +125,7 @@ private:
target_addr_t fPreviousFrameAddress;
bool fSingleStepping;
sem_id fConditionWaitSem;
Value* fConditionResult;
ExpressionResult* fConditionResult;
public:
ThreadHandler* fNext;

View File

@ -19,6 +19,7 @@
#include "Value.h"
#include "ValueNode.h"
#include "ValueNodeManager.h"
#include "Variable.h"
ExpressionEvaluationJob::ExpressionEvaluationJob(Team* team,
@ -89,10 +90,8 @@ ExpressionEvaluationJob::Do()
}
ValueNode* neededNode = NULL;
PrimitiveType* type = dynamic_cast<PrimitiveType*>(
fExpressionInfo->ResultType());
result = fLanguage->EvaluateExpression(fExpressionInfo->Expression(),
type->TypeConstant(), fManager, fResultValue, neededNode);
fManager, fResultValue, neededNode);
if (neededNode != NULL) {
result = ResolveNodeValue(neededNode);
if (State() == JOB_STATE_WAITING)

View File

@ -19,6 +19,7 @@ class BVariant;
class CpuState;
class DebuggerInterface;
class ExpressionInfo;
class ExpressionResult;
class Function;
class FunctionInstance;
class Image;
@ -245,7 +246,7 @@ public:
virtual const JobKey& Key() const;
virtual status_t Do();
Value* GetResultValue() const { return fResultValue; }
ExpressionResult* GetResult() const { return fResultValue; }
private:
status_t ResolveNodeValue(ValueNode* node);
@ -261,7 +262,7 @@ private:
StackFrame* fFrame;
Thread* fThread;
ValueNodeManager* fManager;
Value* fResultValue;
ExpressionResult* fResultValue;
};

View File

@ -6,70 +6,123 @@
#include "ExpressionInfo.h"
#include "Type.h"
#include "Value.h"
#include "ValueNode.h"
// #pragma mark - ExpressionResult
ExpressionResult::ExpressionResult()
:
fResultKind(EXPRESSION_RESULT_KIND_UNKNOWN),
fPrimitiveValue(NULL),
fValueNodeValue(NULL)
{
}
ExpressionResult::~ExpressionResult()
{
if (fPrimitiveValue != NULL)
fPrimitiveValue->ReleaseReference();
if (fValueNodeValue != NULL)
fValueNodeValue->ReleaseReference();
}
void
ExpressionResult::SetToPrimitive(Value* value)
{
_Unset();
fPrimitiveValue = value;
if (fPrimitiveValue != NULL) {
fPrimitiveValue->AcquireReference();
fResultKind = EXPRESSION_RESULT_KIND_PRIMITIVE;
}
}
void
ExpressionResult::SetToValueNode(ValueNodeChild* child)
{
_Unset();
fValueNodeValue = child;
if (fValueNodeValue != NULL) {
fValueNodeValue->AcquireReference();
fResultKind = EXPRESSION_RESULT_KIND_VALUE_NODE;
}
// if the child has a node with a resolved value, store
// it as a primitive, so the consumer of the expression
// can use it as-is if desired.
ValueNode* node = child->Node();
if (node == NULL)
return;
fPrimitiveValue = node->GetValue();
if (fPrimitiveValue != NULL)
fPrimitiveValue->AcquireReference();
}
void
ExpressionResult::_Unset()
{
if (fPrimitiveValue != NULL) {
fPrimitiveValue->ReleaseReference();
fPrimitiveValue = NULL;
}
if (fValueNodeValue != NULL) {
fValueNodeValue->ReleaseReference();
fValueNodeValue = NULL;
}
fResultKind = EXPRESSION_RESULT_KIND_UNKNOWN;
}
// #pragma mark - ExpressionInfo
ExpressionInfo::ExpressionInfo()
:
fExpression(),
fResultType(NULL)
fExpression()
{
}
ExpressionInfo::ExpressionInfo(const ExpressionInfo& other)
:
fExpression(other.fExpression),
fResultType(other.fResultType)
fExpression(other.fExpression)
{
if (fResultType != NULL)
fResultType->AcquireReference();
}
ExpressionInfo::~ExpressionInfo()
{
SetResultType(NULL);
}
ExpressionInfo::ExpressionInfo(const BString& expression, Type* resultType)
ExpressionInfo::ExpressionInfo(const BString& expression)
:
fExpression(expression),
fResultType(resultType)
fExpression(expression)
{
if (resultType != NULL)
resultType->AcquireReference();
}
void
ExpressionInfo::SetTo(const BString& expression, Type* resultType)
{
SetExpression(expression);
SetResultType(resultType);
}
void
ExpressionInfo::SetExpression(const BString& expression)
ExpressionInfo::SetTo(const BString& expression)
{
fExpression = expression;
}
void
ExpressionInfo::SetResultType(Type* resultType)
{
if (fResultType != NULL)
fResultType->ReleaseReference();
fResultType = resultType;
if (fResultType != NULL)
fResultType->AcquireReference();
}
void
ExpressionInfo::AddListener(Listener* listener)
{
@ -85,7 +138,8 @@ ExpressionInfo::RemoveListener(Listener* listener)
void
ExpressionInfo::NotifyExpressionEvaluated(status_t result, Value* value)
ExpressionInfo::NotifyExpressionEvaluated(status_t result,
ExpressionResult* value)
{
for (ListenerList::Iterator it = fListeners.GetIterator();
Listener* listener = it.Next();) {

View File

@ -10,9 +10,44 @@
#include <Referenceable.h>
#include <util/DoublyLinkedList.h>
#include <Variant.h>
class Type;
class Value;
class ValueNodeChild;
enum expression_result_kind {
EXPRESSION_RESULT_KIND_UNKNOWN = 0,
EXPRESSION_RESULT_KIND_PRIMITIVE,
EXPRESSION_RESULT_KIND_VALUE_NODE
};
class ExpressionResult : public BReferenceable {
public:
ExpressionResult();
virtual ~ExpressionResult();
expression_result_kind Kind() const { return fResultKind; }
Value* PrimitiveValue() const
{ return fPrimitiveValue; }
ValueNodeChild* ValueNodeValue() const
{ return fValueNodeValue; }
void SetToPrimitive(Value* value);
void SetToValueNode(ValueNodeChild* child);
private:
void _Unset();
private:
expression_result_kind fResultKind;
Value* fPrimitiveValue;
ValueNodeChild* fValueNodeValue;
};
class ExpressionInfo : public BReferenceable {
@ -22,31 +57,24 @@ public:
public:
ExpressionInfo();
ExpressionInfo(const ExpressionInfo& other);
ExpressionInfo(const BString& expression,
Type* resultType);
ExpressionInfo(const BString& expression);
virtual ~ExpressionInfo();
void SetTo(const BString& expression,
Type* resultType);
void SetTo(const BString& expression);
const BString& Expression() const { return fExpression; }
void SetExpression(const BString& expression);
Type* ResultType() const { return fResultType; }
void SetResultType(Type* resultType);
void AddListener(Listener* listener);
void RemoveListener(Listener* listener);
void NotifyExpressionEvaluated(status_t result,
Value* value);
ExpressionResult* value);
private:
typedef DoublyLinkedList<Listener> ListenerList;
private:
BString fExpression;
Type* fResultType;
ListenerList fListeners;
};
@ -56,7 +84,8 @@ public:
virtual ~Listener();
virtual void ExpressionEvaluated(ExpressionInfo* info,
status_t result, Value* value) = 0;
status_t result,
ExpressionResult* value) = 0;
};

View File

@ -11,11 +11,9 @@
#include <stdlib.h>
#include "CLanguageExpressionEvaluator.h"
#include "FloatValue.h"
#include "IntegerValue.h"
#include "Number.h"
#include "StringValue.h"
#include "ExpressionInfo.h"
#include "TeamTypeInformation.h"
#include "StringValue.h"
#include "Type.h"
#include "TypeLookupConstraints.h"
@ -167,46 +165,28 @@ CLanguageFamily::ParseTypeExpression(const BString& expression,
status_t
CLanguageFamily::EvaluateExpression(const BString& expression, type_code type,
ValueNodeManager* manager, Value*& _output, ValueNode*& _neededNode)
CLanguageFamily::EvaluateExpression(const BString& expression,
ValueNodeManager* manager, ExpressionResult*& _output,
ValueNode*& _neededNode)
{
_output = NULL;
_neededNode = NULL;
CLanguageExpressionEvaluator evaluator;
Number result;
try {
result = evaluator.Evaluate(expression, type, manager);
BVariant resultValue = result.GetValue();
switch (type) {
case B_INT8_TYPE:
case B_UINT8_TYPE:
case B_INT16_TYPE:
case B_UINT16_TYPE:
case B_INT32_TYPE:
case B_UINT32_TYPE:
case B_INT64_TYPE:
case B_UINT64_TYPE:
_output = new(std::nothrow) IntegerValue(resultValue);
break;
case B_FLOAT_TYPE:
_output = new(std::nothrow) FloatValue(resultValue.ToFloat());
break;
case B_DOUBLE_TYPE:
_output = new(std::nothrow) FloatValue(resultValue.ToDouble());
break;
}
if (_output == NULL)
return B_NO_MEMORY;
_output = evaluator.Evaluate(expression, manager);
return B_OK;
} catch (ParseException ex) {
BString stringValue;
stringValue.SetToFormat("Parse error at position %" B_PRId32 ": %s",
BString error;
error.SetToFormat("Parse error at position %" B_PRId32 ": %s",
ex.position, ex.message.String());
_output = new(std::nothrow) StringValue(stringValue);
StringValue* value = new(std::nothrow) StringValue(error.String());
if (value == NULL)
return B_NO_MEMORY;
BReference<Value> valueReference(value, true);
_output = new(std::nothrow) ExpressionResult();
if (_output == NULL)
return B_NO_MEMORY;
_output->SetToPrimitive(value);
return B_BAD_DATA;
} catch (ValueNeededException ex) {
_neededNode = ex.value;

View File

@ -22,8 +22,9 @@ public:
Type*& _resultType) const;
virtual status_t EvaluateExpression(const BString& expression,
type_code type, ValueNodeManager* manager,
Value*& _output, ValueNode*& _neededNode);
ValueNodeManager* manager,
ExpressionResult*& _output,
ValueNode*& _neededNode);
protected:
virtual bool IsModifierValid(char modifier) const = 0;

View File

@ -30,7 +30,7 @@ SourceLanguage::ParseTypeExpression(const BString& expression,
status_t
SourceLanguage::EvaluateExpression(const BString& expression,
type_code type, ValueNodeManager* manager, Value*& _resultValue,
ValueNodeManager* manager, ExpressionResult*& _resultValue,
ValueNode*& _neededNode)
{
return B_NOT_SUPPORTED;

View File

@ -11,10 +11,10 @@
class BString;
class ExpressionResult;
class SyntaxHighlighter;
class TeamTypeInformation;
class Type;
class Value;
class ValueNode;
class ValueNodeManager;
@ -34,8 +34,9 @@ public:
Type*& _resultType) const;
virtual status_t EvaluateExpression(const BString& expression,
type_code type, ValueNodeManager* manager,
Value*& _output, ValueNode*& _neededNode);
ValueNodeManager* manager,
ExpressionResult*& _output,
ValueNode*& _neededNode);
};

View File

@ -18,6 +18,7 @@
class ValueNode;
class ValueNodeChild;
class ValueNodeManager;
class Variable;
class ParseException {
@ -38,6 +39,7 @@ class ParseException {
int32 position;
};
class ValueNeededException {
public:
ValueNeededException(ValueNode* node)
@ -50,6 +52,7 @@ public:
};
class ExpressionResult;
class Number;
@ -59,31 +62,28 @@ class CLanguageExpressionEvaluator {
CLanguageExpressionEvaluator();
~CLanguageExpressionEvaluator();
Number Evaluate(const char* expressionString,
type_code type, ValueNodeManager* manager);
ExpressionResult* Evaluate(const char* expressionString,
ValueNodeManager* manager);
private:
class Operand;
struct Token;
class Tokenizer;
private:
Number _ParseSum();
Number _ParseProduct();
Number _ParsePower();
Number _ParseUnary();
Number _ParseIdentifier(ValueNode* parentNode = NULL);
Number _ParseAtom();
Operand _ParseSum();
Operand _ParseProduct();
Operand _ParsePower();
Operand _ParseUnary();
Operand _ParseIdentifier(ValueNode* parentNode = NULL);
Operand _ParseAtom();
void _EatToken(int32 type);
void _RequestValueIfNeeded(const Token& token,
ValueNodeChild* child);
void _CoerceTypeIfNeeded(const Token& token,
Number& _number);
Tokenizer* fTokenizer;
type_code fCurrentType;
ValueNodeManager* fNodeManager;
};

File diff suppressed because it is too large Load Diff

View File

@ -1,58 +0,0 @@
/*
* Copyright 2014, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License.
*/
#ifndef NUMBER_H
#define NUMBER_H
#include <TypeConstants.h>
#include "Variant.h"
class BString;
class Number {
public:
Number();
virtual ~Number();
Number(type_code type, const BString& value);
Number(const BVariant& value);
Number(const Number& other);
void SetTo(type_code type, const BString& value,
int32 base = 10);
void SetTo(const BVariant& value);
type_code Type() const { return fValue.Type(); }
Number& operator=(const Number& rhs);
Number& operator+=(const Number& rhs);
Number& operator-=(const Number& rhs);
Number& operator/=(const Number& rhs);
Number& operator*=(const Number& rhs);
Number& operator%=(const Number& rhs);
Number& operator&=(const Number& rhs);
Number& operator|=(const Number& rhs);
Number& operator^=(const Number& rhs);
Number operator-() const;
Number operator~() const;
int operator<(const Number& rhs) const;
int operator<=(const Number& rhs) const;
int operator>(const Number& rhs) const;
int operator>=(const Number& rhs) const;
int operator==(const Number& rhs) const;
int operator!=(const Number& rhs) const;
BVariant GetValue() const;
private:
BVariant fValue;
};
#endif // NUMBER_H

View File

@ -12,8 +12,9 @@
#include "StackTrace.h"
#include "UserInterface.h"
#include "Value.h"
#include "ValueNodeManager.h"
#include "Variable.h"
// NOTE: This is a simple work-around for EditLine not having any kind of user
// data field. Hence in _GetPrompt() we don't have access to the context object.
@ -29,7 +30,7 @@ static CliContext* sCurrentContext;
struct CliContext::Event : DoublyLinkedListLinkImpl<CliContext::Event> {
Event(int type, Thread* thread = NULL, TeamMemoryBlock* block = NULL,
ExpressionInfo* info = NULL, status_t expressionResult = B_OK,
Value* expressionValue = NULL)
ExpressionResult* expressionValue = NULL)
:
fType(type),
fThreadReference(thread),
@ -65,7 +66,7 @@ struct CliContext::Event : DoublyLinkedListLinkImpl<CliContext::Event> {
return fExpressionResult;
}
Value* GetExpressionValue() const
ExpressionResult* GetExpressionValue() const
{
return fExpressionValue.Get();
}
@ -77,7 +78,7 @@ private:
BReference<TeamMemoryBlock> fMemoryBlockReference;
BReference<ExpressionInfo> fExpressionInfo;
status_t fExpressionResult;
BReference<Value> fExpressionValue;
BReference<ExpressionResult> fExpressionValue;
};
@ -509,7 +510,7 @@ CliContext::ThreadStackTraceChanged(const Team::ThreadEvent& threadEvent)
void
CliContext::ExpressionEvaluated(ExpressionInfo* info, status_t result,
Value* value)
ExpressionResult* value)
{
_QueueEvent(
new(std::nothrow) Event(EVENT_EXPRESSION_EVALUATED,

View File

@ -85,7 +85,7 @@ public:
{ return fExpressionInfo; }
status_t GetExpressionResult() const
{ return fExpressionResult; }
Value* GetExpressionValue() const
ExpressionResult* GetExpressionValue() const
{ return fExpressionValue; }
const char* PromptUser(const char* prompt);
@ -120,7 +120,7 @@ private:
// ExpressionInfo::Listener
virtual void ExpressionEvaluated(ExpressionInfo* info,
status_t result, Value* value);
status_t result, ExpressionResult* value);
// ValueNodeContainer::Listener
virtual void ValueNodeChanged(ValueNodeChild* nodeChild,
@ -160,7 +160,7 @@ private:
ExpressionInfo* fExpressionInfo;
status_t fExpressionResult;
Value* fExpressionValue;
ExpressionResult* fExpressionValue;
EventList fPendingEvents;
};

View File

@ -18,12 +18,12 @@
#include "CliContext.h"
#include "CppLanguage.h"
#include "SyntheticPrimitiveType.h"
#include "Team.h"
#include "TeamMemoryBlock.h"
#include "UiUtils.h"
#include "UserInterface.h"
#include "Value.h"
#include "Variable.h"
CliDumpMemoryCommand::CliDumpMemoryCommand()
@ -60,22 +60,7 @@ CliDumpMemoryCommand::Execute(int argc, const char* const* argv,
ExpressionInfo* info = context.GetExpressionInfo();
target_addr_t address = 0;
PrimitiveType* type = dynamic_cast<PrimitiveType*>(info->ResultType());
if (type == NULL || type->TypeConstant() != B_UINT64_TYPE) {
type = new(std::nothrow) SyntheticPrimitiveType(
B_UINT64_TYPE);
if (type == NULL) {
printf("Unable to evaluate expression: %s\n", strerror(B_NO_MEMORY));
return;
}
BReference<Type> typeReference(type, true);
info->SetResultType(type);
}
info->SetExpression(argv[1]);
info->SetTo(argv[1]);
context.GetUserInterfaceListener()->ExpressionEvaluationRequested(
fLanguage, info);
@ -84,14 +69,17 @@ CliDumpMemoryCommand::Execute(int argc, const char* const* argv,
return;
BString errorMessage;
Value* value = context.GetExpressionValue();
if (value != NULL) {
BVariant variantValue;
value->ToVariant(variantValue);
if (variantValue.Type() == B_UINT64_TYPE)
address = variantValue.ToUInt64();
else
value->ToString(errorMessage);
ExpressionResult* result = context.GetExpressionValue();
if (result != NULL) {
if (result->Kind() == EXPRESSION_RESULT_KIND_PRIMITIVE) {
Value* value = result->PrimitiveValue();
BVariant variantValue;
value->ToVariant(variantValue);
if (variantValue.Type() == B_STRING_TYPE)
errorMessage.SetTo(variantValue.ToString());
else
address = variantValue.ToUInt64();
}
} else
errorMessage = strerror(context.GetExpressionResult());

View File

@ -19,12 +19,11 @@
#include "Architecture.h"
#include "CppLanguage.h"
#include "GuiTeamUiSettings.h"
#include "IntegerValue.h"
#include "MemoryView.h"
#include "MessageCodes.h"
#include "SyntheticPrimitiveType.h"
#include "Team.h"
#include "UserInterface.h"
#include "Value.h"
enum {
@ -94,9 +93,7 @@ void
InspectorWindow::_Init()
{
fLanguage = new CppLanguage();
::Type* type = new SyntheticPrimitiveType(B_UINT64_TYPE);
BReference< ::Type> typeReference(type);
fExpressionInfo = new ExpressionInfo(NULL, type);
fExpressionInfo = new ExpressionInfo();
fExpressionInfo->AddListener(this);
BScrollView* scrollView;
@ -236,7 +233,7 @@ InspectorWindow::MessageReceived(BMessage* message)
if (fAddressInput->TextView()->TextLength() == 0)
break;
fExpressionInfo->SetExpression(fAddressInput->Text());
fExpressionInfo->SetTo(fAddressInput->Text());
fListener->ExpressionEvaluationRequested(fLanguage,
fExpressionInfo);
@ -247,18 +244,22 @@ InspectorWindow::MessageReceived(BMessage* message)
case MSG_EXPRESSION_EVALUATED:
{
BString errorMessage;
BReference<Value> reference;
Value* value = NULL;
BReference<ExpressionResult> reference;
ExpressionResult* value = NULL;
if (message->FindPointer("value",
reinterpret_cast<void**>(&value)) == B_OK) {
reference.SetTo(value, true);
BVariant variant;
value->ToVariant(variant);
if (variant.Type() == B_UINT64_TYPE) {
_SetToAddress(variant.ToUInt64());
break;
} else
value->ToString(errorMessage);
if (value->Kind() == EXPRESSION_RESULT_KIND_PRIMITIVE) {
Value* primitive = value->PrimitiveValue();
BVariant variantValue;
primitive->ToVariant(variantValue);
if (variantValue.Type() == B_STRING_TYPE) {
errorMessage.SetTo(variantValue.ToString());
} else {
_SetToAddress(variantValue.ToUInt64());
break;
}
}
} else {
status_t result = message->FindInt32("result");
errorMessage.SetToFormat("Failed to evaluate expression: %s",
@ -385,11 +386,11 @@ InspectorWindow::TargetAddressChanged(target_addr_t address)
void
InspectorWindow::ExpressionEvaluated(ExpressionInfo* info, status_t result,
Value* value)
ExpressionResult* value)
{
BMessage message(MSG_EXPRESSION_EVALUATED);
message.AddInt32("result", result);
BReference<Value> reference;
BReference<ExpressionResult> reference;
if (value != NULL) {
reference.SetTo(value);
message.AddPointer("value", value);

View File

@ -55,7 +55,7 @@ public:
// ExpressionInfo::Listener
virtual void ExpressionEvaluated(ExpressionInfo* info,
status_t result, Value* value);
status_t result, ExpressionResult* value);
status_t LoadSettings(
const GuiTeamUiSettings& settings);

View File

@ -14,6 +14,7 @@
#include "AutoLocker.h"
#include "IntegerValue.h"
#include "MessageCodes.h"
#include "SourceLanguage.h"
#include "StackFrame.h"
@ -21,12 +22,6 @@
#include "Thread.h"
#include "UiUtils.h"
#include "UserInterface.h"
#include "Value.h"
enum {
MSG_CHANGE_EVALUATION_TYPE = 'chet'
};
ExpressionEvaluationWindow::ExpressionEvaluationWindow(
@ -91,9 +86,8 @@ ExpressionEvaluationWindow::Create(SourceLanguage* language, StackFrame* frame,
void
ExpressionEvaluationWindow::_Init()
{
::Type* type = new SyntheticPrimitiveType(B_INT64_TYPE);
BReference< ::Type> typeReference(type, true);
fExpressionInfo = new ExpressionInfo(NULL, type);
fExpressionInfo = new ExpressionInfo;
fExpressionInfo->AddListener(this);
fExpressionInput = new BTextControl("Expression:", NULL,
new BMessage(MSG_EVALUATE_EXPRESSION));
@ -107,16 +101,11 @@ ExpressionEvaluationWindow::_Init()
fExpressionOutput->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED,
B_SIZE_UNSET));
BMenuField* typeField = new BMenuField("Type:", _BuildTypesMenu());
typeField->Menu()->SetTargetForItems(this);
BLayoutBuilder::Group<>(this, B_VERTICAL)
.SetInsets(B_USE_DEFAULT_SPACING)
.AddGroup(B_HORIZONTAL, 4.0f)
.Add(labelItem)
.Add(inputItem)
.Add(typeField->CreateLabelLayoutItem())
.Add(typeField->CreateMenuBarLayoutItem())
.End()
.AddGroup(B_HORIZONTAL, 4.0f)
.Add(new BStringView("OutputLabelView", "Result:"))
@ -130,54 +119,18 @@ ExpressionEvaluationWindow::_Init()
fExpressionInput->SetTarget(this);
fEvaluateButton->SetTarget(this);
fEvaluateButton->MakeDefault(true);
fExpressionInput->TextView()->MakeFocus(true);
}
BMenu*
ExpressionEvaluationWindow::_BuildTypesMenu()
{
BMenu* menu = new BMenu("Types");
menu->SetLabelFromMarked(true);
_AddMenuItemForType(menu, B_INT8_TYPE);
_AddMenuItemForType(menu, B_UINT8_TYPE);
_AddMenuItemForType(menu, B_INT16_TYPE);
_AddMenuItemForType(menu, B_UINT16_TYPE);
_AddMenuItemForType(menu, B_INT32_TYPE);
_AddMenuItemForType(menu, B_UINT32_TYPE);
BMenuItem* item = _AddMenuItemForType(menu, B_INT64_TYPE);
if (item != NULL)
item->SetMarked(true);
_AddMenuItemForType(menu, B_UINT64_TYPE);
_AddMenuItemForType(menu, B_FLOAT_TYPE);
_AddMenuItemForType(menu, B_DOUBLE_TYPE);
return menu;
}
BMenuItem*
ExpressionEvaluationWindow::_AddMenuItemForType(BMenu* menu, type_code type)
{
BMessage *message = new BMessage(MSG_CHANGE_EVALUATION_TYPE);
message->AddInt32("type", type);
BMenuItem* item = new BMenuItem(UiUtils::TypeCodeToString(type), message);
menu->AddItem(item);
return item;
}
void
ExpressionEvaluationWindow::ExpressionEvaluated(ExpressionInfo* info,
status_t result, Value* value)
status_t result, ExpressionResult* value)
{
BMessage message(MSG_EXPRESSION_EVALUATED);
message.AddInt32("result", result);
BReference<Value> reference;
BReference<ExpressionResult> reference;
if (value != NULL) {
message.AddPointer("value", value);
reference.SetTo(value);
@ -215,35 +168,16 @@ ExpressionEvaluationWindow::MessageReceived(BMessage* message)
if (fExpressionInput->TextView()->TextLength() == 0)
break;
fExpressionInfo->SetExpression(fExpressionInput->Text());
fExpressionInfo->SetTo(fExpressionInput->Text());
fListener->ExpressionEvaluationRequested(fLanguage,
fExpressionInfo, fStackFrame, fThread);
break;
}
case MSG_CHANGE_EVALUATION_TYPE:
{
uint32 typeConstant = message->FindInt32("type");
PrimitiveType* type = dynamic_cast<PrimitiveType*>(
fExpressionInfo->ResultType());
if (type->TypeConstant() == typeConstant)
break;
type = new(std::nothrow) SyntheticPrimitiveType(
typeConstant);
if (type == NULL)
break;
BReference< ::Type> typeReference(type, true);
fExpressionInfo->SetResultType(type);
break;
}
case MSG_EXPRESSION_EVALUATED:
{
Value* value = NULL;
BReference<Value> reference;
ExpressionResult* value = NULL;
BReference<ExpressionResult> reference;
if (message->FindPointer("value",
reinterpret_cast<void**>(&value)) == B_OK) {
reference.SetTo(value, true);
@ -251,14 +185,20 @@ ExpressionEvaluationWindow::MessageReceived(BMessage* message)
BString outputText;
if (value != NULL) {
BVariant variantValue;
value->ToVariant(variantValue);
if (variantValue.TypeIsInteger(variantValue.Type())) {
value->ToString(outputText);
outputText.SetToFormat("%#" B_PRIx64 " (%s)",
variantValue.ToUInt64(), outputText.String());
} else
value->ToString(outputText);
if (value->Kind() == EXPRESSION_RESULT_KIND_PRIMITIVE) {
Value* primitive = value->PrimitiveValue();
if (dynamic_cast<IntegerValue*>(primitive) != NULL) {
BVariant variantValue;
primitive->ToVariant(variantValue);
primitive->ToString(outputText);
outputText.SetToFormat("%#" B_PRIx64 " (%s)",
variantValue.ToUInt64(), outputText.String());
} else
primitive->ToString(outputText);
} else {
outputText.SetToFormat("Unsupported result type: %d",
value->Kind());
}
} else {
status_t result;
if (message->FindInt32("result", &result) != B_OK)
@ -271,8 +211,6 @@ ExpressionEvaluationWindow::MessageReceived(BMessage* message)
fExpressionOutput->SetText(outputText);
break;
}
default:
BWindow::MessageReceived(message);
break;

View File

@ -9,16 +9,12 @@
#include <Window.h>
#include "ExpressionInfo.h"
#include "types/Types.h"
class BMenu;
class BMenuItem;
class BButton;
class BStringView;
class BTextControl;
class Thread;
class PrimitiveType;
class SourceLanguage;
class StackFrame;
class UserInterfaceListener;
@ -53,13 +49,10 @@ public:
private:
void _Init();
BMenu* _BuildTypesMenu();
BMenuItem* _AddMenuItemForType(BMenu* menu,
type_code type);
// ExpressionInfo::Listener
virtual void ExpressionEvaluated(ExpressionInfo* info,
status_t result, Value* value);
status_t result, ExpressionResult* value);
private:
SourceLanguage* fLanguage;

View File

@ -6,17 +6,10 @@
#include <Button.h>
#include <LayoutBuilder.h>
#include <MenuField.h>
#include <String.h>
#include <TextControl.h>
#include "MessageCodes.h"
#include "UiUtils.h"
enum {
MSG_CHANGE_EVALUATION_TYPE = 'chet',
};
ExpressionPromptWindow::ExpressionPromptWindow(BHandler* addTarget,
@ -28,8 +21,7 @@ ExpressionPromptWindow::ExpressionPromptWindow(BHandler* addTarget,
fCancelButton(NULL),
fAddButton(NULL),
fAddTarget(addTarget),
fCloseTarget(closeTarget),
fCurrentType(B_INT64_TYPE)
fCloseTarget(closeTarget)
{
}
@ -68,16 +60,11 @@ ExpressionPromptWindow::_Init()
inputItem->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
labelItem->View()->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
BMenuField* typeField = new BMenuField("Type:", _BuildTypesMenu());
typeField->Menu()->SetTargetForItems(this);
BLayoutBuilder::Group<>(this, B_VERTICAL)
.SetInsets(B_USE_DEFAULT_SPACING)
.AddGroup(B_HORIZONTAL, 4.0f)
.Add(labelItem)
.Add(inputItem)
.Add(typeField->CreateLabelLayoutItem())
.Add(typeField->CreateMenuBarLayoutItem())
.End()
.AddGroup(B_HORIZONTAL, 4.0f)
.AddGlue()
@ -95,43 +82,6 @@ ExpressionPromptWindow::_Init()
}
BMenu*
ExpressionPromptWindow::_BuildTypesMenu()
{
BMenu* menu = new BMenu("Types");
menu->SetLabelFromMarked(true);
_AddMenuItemForType(menu, B_INT8_TYPE);
_AddMenuItemForType(menu, B_UINT8_TYPE);
_AddMenuItemForType(menu, B_INT16_TYPE);
_AddMenuItemForType(menu, B_UINT16_TYPE);
_AddMenuItemForType(menu, B_INT32_TYPE);
_AddMenuItemForType(menu, B_UINT32_TYPE);
BMenuItem* item = _AddMenuItemForType(menu, B_INT64_TYPE);
if (item != NULL)
item->SetMarked(true);
_AddMenuItemForType(menu, B_UINT64_TYPE);
_AddMenuItemForType(menu, B_FLOAT_TYPE);
_AddMenuItemForType(menu, B_DOUBLE_TYPE);
return menu;
}
BMenuItem*
ExpressionPromptWindow::_AddMenuItemForType(BMenu* menu, type_code type)
{
BMessage *message = new BMessage(MSG_CHANGE_EVALUATION_TYPE);
message->AddInt32("type", type);
BMenuItem* item = new BMenuItem(UiUtils::TypeCodeToString(type), message);
menu->AddItem(item);
return item;
}
void
ExpressionPromptWindow::Show()
{
@ -154,17 +104,10 @@ void
ExpressionPromptWindow::MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_CHANGE_EVALUATION_TYPE:
{
fCurrentType = message->FindInt32("type");
break;
}
case MSG_ADD_NEW_EXPRESSION:
{
BMessage addMessage(MSG_EXPRESSION_PROMPT_WINDOW_CLOSED);
addMessage.AddString("expression", fExpressionInput->Text());
addMessage.AddInt32("type", fCurrentType);
addMessage.AddMessenger("target", BMessenger(fAddTarget));
BMessenger(fCloseTarget).SendMessage(&addMessage);

View File

@ -10,8 +10,6 @@
class BButton;
class BMenu;
class BMenuItem;
class BTextControl;
@ -35,9 +33,6 @@ public:
private:
void _Init();
BMenu* _BuildTypesMenu();
BMenuItem* _AddMenuItemForType(BMenu* menu,
type_code type);
private:
BTextControl* fExpressionInput;
@ -45,7 +40,6 @@ private:
BButton* fAddButton;
BHandler* fAddTarget;
BHandler* fCloseTarget;
type_code fCurrentType;
};
#endif // EXPRESSION_PROMPT_WINDOW_H

View File

@ -406,15 +406,12 @@ TeamWindow::MessageReceived(BMessage* message)
fExpressionPromptWindow = NULL;
const char* expression;
int32 type;
BMessenger targetMessenger;
if (message->FindString("expression", &expression) == B_OK
&& message->FindInt32("type", &type) == B_OK
&& message->FindMessenger("target", &targetMessenger)
== B_OK) {
BMessage addMessage(MSG_ADD_NEW_EXPRESSION);
addMessage.AddString("expression", expression);
addMessage.AddInt32("type", type);
targetMessenger.SendMessage(&addMessage);
}

View File

@ -1944,18 +1944,11 @@ VariablesView::MessageReceived(BMessage* message)
case MSG_ADD_NEW_EXPRESSION:
{
const char* expression;
int32 type;
Type* resultType;
if (message->FindString("expression", &expression) != B_OK
|| message->FindInt32("type", &type) != B_OK
|| _GetTypeForTypeCode(type, resultType) != B_OK) {
if (message->FindString("expression", &expression) != B_OK)
break;
}
BReference<Type> typeReference(resultType, true);
ExpressionInfo* info;
status_t error = _AddExpression(expression, resultType, info);
status_t error = _AddExpression(expression, info);
if (error != B_OK) {
// TODO: notify user of failure
break;
@ -1969,14 +1962,14 @@ VariablesView::MessageReceived(BMessage* message)
{
ExpressionInfo* info;
status_t result;
Value* value = NULL;
ExpressionResult* value = NULL;
if (message->FindPointer("info",
reinterpret_cast<void**>(&info)) != B_OK
|| message->FindInt32("result", &result) != B_OK) {
break;
}
BReference<Value> valueReference;
BReference<ExpressionResult> valueReference;
if (message->FindPointer("value", reinterpret_cast<void**>(&value))
== B_OK) {
valueReference.SetTo(value, true);
@ -2231,12 +2224,12 @@ VariablesView::TreeTableCellMouseDown(TreeTable* table,
void
VariablesView::ExpressionEvaluated(ExpressionInfo* info, status_t result,
Value* value)
ExpressionResult* value)
{
BMessage message(MSG_EXPRESSION_EVALUATED);
message.AddPointer("info", info);
message.AddInt32("result", result);
BReference<Value> valueReference;
BReference<ExpressionResult> valueReference;
if (value != NULL) {
valueReference.SetTo(value);
@ -2417,6 +2410,7 @@ VariablesView::_GetContextActionsForNode(ModelNode* node,
BPrivate::ObjectDeleter<ContextActionList> postActionListDeleter(
_postActions);
#if 0
result = _AddContextAction("Add watch expression" B_UTF8_ELLIPSIS,
MSG_ADD_WATCH_EXPRESSION, _postActions, message);
if (result != B_OK)
@ -2429,6 +2423,7 @@ VariablesView::_GetContextActionsForNode(ModelNode* node,
return result;
message->AddPointer("node", node);
}
#endif
preActionListDeleter.Detach();
postActionListDeleter.Detach();
@ -2748,8 +2743,7 @@ VariablesView::_CopyVariableValueToClipboard()
status_t
VariablesView::_AddExpression(const char* expression, Type* resultType,
ExpressionInfo*& _info)
VariablesView::_AddExpression(const char* expression, ExpressionInfo*& _info)
{
// if our stack frame doesn't have an associated function,
// we can't add an expression
@ -2775,8 +2769,7 @@ VariablesView::_AddExpression(const char* expression, Type* resultType,
}
}
ExpressionInfo* info = new(std::nothrow) ExpressionInfo(expression,
resultType);
ExpressionInfo* info = new(std::nothrow) ExpressionInfo(expression);
if (info == NULL)
return B_NO_MEMORY;
@ -2829,7 +2822,7 @@ VariablesView::_RemoveExpression(ModelNode* node)
status_t
VariablesView::_AddExpressionNode(ExpressionInfo* info)
{
Type* type = info->ResultType();
#if 0
ExpressionValueNodeChild* child
= new(std::nothrow) ExpressionValueNodeChild(info->Expression(), type);
if (child == NULL)
@ -2859,7 +2852,10 @@ VariablesView::_AddExpressionNode(ExpressionInfo* info)
expressionNodeReference.Detach();
modelNodeReference.Detach();
return B_OK;
#endif
return B_NOT_SUPPORTED;
}
@ -2890,7 +2886,7 @@ VariablesView::_RestoreExpressionNodes()
void
VariablesView::_SetExpressionNodeValue(ExpressionInfo* info, status_t result,
Value* value)
ExpressionResult* value)
{
FunctionInstance* instance = fStackFrame->Function();
if (instance == NULL)
@ -2918,7 +2914,8 @@ VariablesView::_SetExpressionNodeValue(ExpressionInfo* info, status_t result,
if (child->GetExpression() != info->Expression())
continue;
child->Node()->SetLocationAndValue(NULL, value, result);
child->Node()->SetLocationAndValue(NULL, value->PrimitiveValue(),
result);
return;
}
}

View File

@ -66,7 +66,7 @@ private:
// ExpressionInfo::Listener
virtual void ExpressionEvaluated(ExpressionInfo* info,
status_t result, Value* value);
status_t result, ExpressionResult* value);
private:
class ContainerListener;
@ -110,7 +110,6 @@ private:
void _CopyVariableValueToClipboard();
status_t _AddExpression(const char* expression,
Type* resultType,
ExpressionInfo*& _info);
void _RemoveExpression(ModelNode* node);
@ -118,7 +117,7 @@ private:
void _RestoreExpressionNodes();
void _SetExpressionNodeValue(ExpressionInfo* info,
status_t result, Value* value);
status_t result, ExpressionResult* value);
status_t _GetTypeForTypeCode(int32 typeCode,
Type*& _resultType) const;

View File

@ -17,10 +17,10 @@
#include "Architecture.h"
#include "CppLanguage.h"
#include "IntegerValue.h"
#include "MessageCodes.h"
#include "SyntheticPrimitiveType.h"
#include "UserInterface.h"
#include "Value.h"
#include "Watchpoint.h"
@ -91,21 +91,15 @@ WatchPromptWindow::_Init()
{
fLanguage = new CppLanguage();
PrimitiveType* type = new SyntheticPrimitiveType(B_UINT64_TYPE);
BReference<PrimitiveType> typeReference(type, true);
BString text;
text.SetToFormat("0x%" B_PRIx64, fInitialAddress);
fAddressInput = new BTextControl("Address:", text, NULL);
fAddressExpressionInfo = new ExpressionInfo(text, type);
fAddressExpressionInfo = new ExpressionInfo(text);
fAddressExpressionInfo->AddListener(this);
type = new SyntheticPrimitiveType(B_INT32_TYPE);
typeReference.SetTo(type, true);
text.SetToFormat("%" B_PRId32, fInitialLength);
fLengthInput = new BTextControl("Length:", text, NULL);
fLengthExpressionInfo = new ExpressionInfo(text, type);
fLengthExpressionInfo = new ExpressionInfo(text);
fLengthExpressionInfo->AddListener(this);
int32 maxDebugRegisters = 0;
@ -170,11 +164,12 @@ WatchPromptWindow::Show()
void
WatchPromptWindow::ExpressionEvaluated(ExpressionInfo* info, status_t result,
Value* value)
ExpressionResult* value)
{
BMessage message(MSG_EXPRESSION_EVALUATED);
message.AddInt32("result", result);
BReference<Value> reference;
message.AddPointer("info", info);
BReference<ExpressionResult> reference;
if (value != NULL) {
reference.SetTo(value);
message.AddPointer("value", value);
@ -192,20 +187,32 @@ WatchPromptWindow::MessageReceived(BMessage* message)
case MSG_EXPRESSION_EVALUATED:
{
BString errorMessage;
BReference<Value> reference;
Value* value = NULL;
BReference<ExpressionResult> reference;
ExpressionResult* value = NULL;
ExpressionInfo* info = NULL;
if (message->FindPointer("info",
reinterpret_cast<void**>(&info)) != B_OK) {
break;
}
if (message->FindPointer("value",
reinterpret_cast<void**>(&value)) == B_OK) {
reference.SetTo(value, true);
BVariant variant;
value->ToVariant(variant);
if (variant.Type() == B_UINT64_TYPE) {
fRequestedAddress = variant.ToUInt64();
break;
} else if (variant.Type() == B_INT32_TYPE)
fRequestedLength = variant.ToInt32();
else
value->ToString(errorMessage);
if (value->Kind() == EXPRESSION_RESULT_KIND_PRIMITIVE) {
Value* primitive = value->PrimitiveValue();
if (dynamic_cast<IntegerValue*>(primitive) != NULL) {
BVariant resultVariant;
primitive->ToVariant(resultVariant);
if (info == fAddressExpressionInfo) {
fRequestedAddress = resultVariant.ToUInt64();
break;
} else
fRequestedLength = resultVariant.ToInt32();
}
else
primitive->ToString(errorMessage);
} else
errorMessage.SetTo("Unsupported expression result.");
} else {
status_t result = message->FindInt32("result");
errorMessage.SetToFormat("Failed to evaluate expression: %s",
@ -237,11 +244,11 @@ WatchPromptWindow::MessageReceived(BMessage* message)
fRequestedAddress = 0;
fRequestedLength = 0;
fAddressExpressionInfo->SetExpression(fAddressInput->Text());
fAddressExpressionInfo->SetTo(fAddressInput->Text());
fListener->ExpressionEvaluationRequested(fLanguage,
fAddressExpressionInfo);
fLengthExpressionInfo->SetExpression(fLengthInput->Text());
fLengthExpressionInfo->SetTo(fLengthInput->Text());
fListener->ExpressionEvaluationRequested(fLanguage,
fLengthExpressionInfo);
break;

View File

@ -43,7 +43,7 @@ public:
// ExpressionInfo::Listener
virtual void ExpressionEvaluated(ExpressionInfo* info,
status_t result, Value* value);
status_t result, ExpressionResult* value);
private:
void _Init();