Debugger: Implement expression variable value resolution.
General: - Resolving variable values requires both a stack frame and a CPU state. Adjust all interfaces and callers accordingly. ExpressionEvaluationJob: - Pass additional parameters needed for variable value resolution. - If variable resolution is desired, ExpressionEvaluationJob now creates a temporary ValueNodeManager for that purpose. - If the expression parser returns a value node pointer that needs to be resolved, schedule a corresponding job and wait. CLanguageExpressionEvaluator: - Clean up some leftovers that were preventing variable names from being handled properly in some cases. - Implement handling of identifier names. These are now looked up against the value node graph of the active node manager, and if found, corresponding values are retrieved. If the value has not yet been resolved, an exception is thrown to ask that to be done. This gets value resolution working for basic local variables and function parameters, and consequently, #9712. Structure/class members and/or pointer indirection aren't yet handled.
This commit is contained in:
@@ -732,7 +732,16 @@ TeamDebugger::MessageReceived(BMessage* message)
|
|||||||
frame = NULL;
|
frame = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
_HandleEvaluateExpression(language, expression, resultType, frame);
|
::Thread* thread;
|
||||||
|
if (message->FindPointer("thread",
|
||||||
|
reinterpret_cast<void**>(&thread)) != B_OK) {
|
||||||
|
// the thread isn't needed, unless variable
|
||||||
|
// evaluation is desired.
|
||||||
|
thread = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
_HandleEvaluateExpression(language, expression, resultType,
|
||||||
|
frame, thread);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1087,7 +1096,8 @@ TeamDebugger::InspectRequested(target_addr_t address,
|
|||||||
|
|
||||||
void
|
void
|
||||||
TeamDebugger::ExpressionEvaluationRequested(SourceLanguage* language,
|
TeamDebugger::ExpressionEvaluationRequested(SourceLanguage* language,
|
||||||
const char* expression, type_code resultType, StackFrame* frame)
|
const char* expression, type_code resultType, StackFrame* frame,
|
||||||
|
::Thread* thread)
|
||||||
{
|
{
|
||||||
BMessage message(MSG_EVALUATE_EXPRESSION);
|
BMessage message(MSG_EVALUATE_EXPRESSION);
|
||||||
message.AddPointer("language", language);
|
message.AddPointer("language", language);
|
||||||
@@ -1095,6 +1105,8 @@ TeamDebugger::ExpressionEvaluationRequested(SourceLanguage* language,
|
|||||||
message.AddInt32("type", resultType);
|
message.AddInt32("type", resultType);
|
||||||
if (frame != NULL)
|
if (frame != NULL)
|
||||||
message.AddPointer("frame", frame);
|
message.AddPointer("frame", frame);
|
||||||
|
if (thread != NULL)
|
||||||
|
message.AddPointer("thread", thread);
|
||||||
|
|
||||||
BReference<SourceLanguage> reference(language);
|
BReference<SourceLanguage> reference(language);
|
||||||
if (PostMessage(&message) == B_OK)
|
if (PostMessage(&message) == B_OK)
|
||||||
@@ -1982,11 +1994,12 @@ TeamDebugger::_HandleInspectAddress(target_addr_t address,
|
|||||||
|
|
||||||
void
|
void
|
||||||
TeamDebugger::_HandleEvaluateExpression(SourceLanguage* language,
|
TeamDebugger::_HandleEvaluateExpression(SourceLanguage* language,
|
||||||
const char* expression, type_code resultType, StackFrame* frame)
|
const char* expression, type_code resultType, StackFrame* frame,
|
||||||
|
::Thread* thread)
|
||||||
{
|
{
|
||||||
status_t result = fWorker->ScheduleJob(
|
status_t result = fWorker->ScheduleJob(
|
||||||
new(std::nothrow) ExpressionEvaluationJob(fTeam, language,
|
new(std::nothrow) ExpressionEvaluationJob(fTeam, fDebuggerInterface,
|
||||||
expression, resultType, frame));
|
language, expression, resultType, frame, thread));
|
||||||
if (result != B_OK) {
|
if (result != B_OK) {
|
||||||
_NotifyUser("Evaluate Expression", "Failed to evaluate expression: %s",
|
_NotifyUser("Evaluate Expression", "Failed to evaluate expression: %s",
|
||||||
strerror(result));
|
strerror(result));
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ class FileManager;
|
|||||||
class SettingsManager;
|
class SettingsManager;
|
||||||
class TeamDebugInfo;
|
class TeamDebugInfo;
|
||||||
class TeamMemoryBlockManager;
|
class TeamMemoryBlockManager;
|
||||||
|
class Thread;
|
||||||
class WatchpointManager;
|
class WatchpointManager;
|
||||||
|
|
||||||
|
|
||||||
@@ -106,7 +107,8 @@ private:
|
|||||||
SourceLanguage* language,
|
SourceLanguage* language,
|
||||||
const char* expression,
|
const char* expression,
|
||||||
type_code resultType,
|
type_code resultType,
|
||||||
StackFrame* frame = NULL);
|
StackFrame* frame = NULL,
|
||||||
|
::Thread* thread = NULL);
|
||||||
|
|
||||||
virtual void DebugReportRequested(entry_ref* targetPath);
|
virtual void DebugReportRequested(entry_ref* targetPath);
|
||||||
|
|
||||||
@@ -193,7 +195,8 @@ private:
|
|||||||
SourceLanguage* language,
|
SourceLanguage* language,
|
||||||
const char* expression,
|
const char* expression,
|
||||||
type_code resultType,
|
type_code resultType,
|
||||||
StackFrame* frame);
|
StackFrame* frame,
|
||||||
|
::Thread* thread);
|
||||||
|
|
||||||
status_t _HandleSetArguments(int argc,
|
status_t _HandleSetArguments(int argc,
|
||||||
const char* const* argv);
|
const char* const* argv);
|
||||||
|
|||||||
@@ -9,26 +9,38 @@
|
|||||||
|
|
||||||
#include <AutoLocker.h>
|
#include <AutoLocker.h>
|
||||||
|
|
||||||
|
#include "DebuggerInterface.h"
|
||||||
#include "SourceLanguage.h"
|
#include "SourceLanguage.h"
|
||||||
#include "StackFrame.h"
|
#include "StackFrame.h"
|
||||||
#include "Team.h"
|
#include "Team.h"
|
||||||
|
#include "Thread.h"
|
||||||
#include "Value.h"
|
#include "Value.h"
|
||||||
|
#include "ValueNode.h"
|
||||||
|
#include "ValueNodeManager.h"
|
||||||
|
|
||||||
|
|
||||||
ExpressionEvaluationJob::ExpressionEvaluationJob(Team* team,
|
ExpressionEvaluationJob::ExpressionEvaluationJob(Team* team,
|
||||||
SourceLanguage* language, const char* expression, type_code resultType,
|
DebuggerInterface* debuggerInterface, SourceLanguage* language,
|
||||||
StackFrame* frame)
|
const char* expression, type_code resultType, StackFrame* frame,
|
||||||
|
Thread* thread)
|
||||||
:
|
:
|
||||||
fKey(expression, JOB_TYPE_EVALUATE_EXPRESSION),
|
fKey(expression, JOB_TYPE_EVALUATE_EXPRESSION),
|
||||||
fTeam(team),
|
fTeam(team),
|
||||||
|
fDebuggerInterface(debuggerInterface),
|
||||||
|
fArchitecture(debuggerInterface->GetArchitecture()),
|
||||||
|
fTypeInformation(team->GetTeamTypeInformation()),
|
||||||
fLanguage(language),
|
fLanguage(language),
|
||||||
fExpression(expression),
|
fExpression(expression),
|
||||||
fResultType(resultType),
|
fResultType(resultType),
|
||||||
fFrame(frame)
|
fFrame(frame),
|
||||||
|
fThread(thread),
|
||||||
|
fManager(NULL)
|
||||||
{
|
{
|
||||||
fLanguage->AcquireReference();
|
fLanguage->AcquireReference();
|
||||||
if (fFrame != NULL)
|
if (fFrame != NULL)
|
||||||
fFrame->AcquireReference();
|
fFrame->AcquireReference();
|
||||||
|
if (fThread != NULL)
|
||||||
|
fThread->AcquireReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -37,6 +49,10 @@ ExpressionEvaluationJob::~ExpressionEvaluationJob()
|
|||||||
fLanguage->ReleaseReference();
|
fLanguage->ReleaseReference();
|
||||||
if (fFrame != NULL)
|
if (fFrame != NULL)
|
||||||
fFrame->ReleaseReference();
|
fFrame->ReleaseReference();
|
||||||
|
if (fThread != NULL)
|
||||||
|
fThread->ReleaseReference();
|
||||||
|
if (fManager != NULL)
|
||||||
|
fManager->ReleaseReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -50,15 +66,80 @@ ExpressionEvaluationJob::Key() const
|
|||||||
status_t
|
status_t
|
||||||
ExpressionEvaluationJob::Do()
|
ExpressionEvaluationJob::Do()
|
||||||
{
|
{
|
||||||
|
|
||||||
Value* value = NULL;
|
Value* value = NULL;
|
||||||
status_t result = fLanguage->EvaluateExpression(fExpression, fResultType,
|
|
||||||
value);
|
|
||||||
BReference<Value> reference;
|
BReference<Value> reference;
|
||||||
if (value != NULL)
|
status_t result = B_OK;
|
||||||
|
if (fFrame != NULL && fManager == NULL) {
|
||||||
|
fManager = new(std::nothrow) ValueNodeManager();
|
||||||
|
if (fManager == NULL)
|
||||||
|
result = B_NO_MEMORY;
|
||||||
|
else
|
||||||
|
result = fManager->SetStackFrame(fThread, fFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result != B_OK) {
|
||||||
|
fTeam->NotifyExpressionEvaluated(fExpression.String(), result, NULL);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueNode* neededNode = NULL;
|
||||||
|
result = fLanguage->EvaluateExpression(fExpression,
|
||||||
|
fResultType, fManager, value, neededNode);
|
||||||
|
if (neededNode != NULL) {
|
||||||
|
result = ResolveNodeValue(neededNode);
|
||||||
|
if (State() == JOB_STATE_WAITING)
|
||||||
|
return B_OK;
|
||||||
|
else if (value != NULL)
|
||||||
reference.SetTo(value, true);
|
reference.SetTo(value, true);
|
||||||
|
// if result != B_OK, fall through
|
||||||
|
}
|
||||||
|
|
||||||
AutoLocker<Team> teamLocker(fTeam);
|
AutoLocker<Team> teamLocker(fTeam);
|
||||||
fTeam->NotifyExpressionEvaluated(fExpression.String(), result, value);
|
fTeam->NotifyExpressionEvaluated(fExpression.String(), result, value);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ExpressionEvaluationJob::ResolveNodeValue(ValueNode* node)
|
||||||
|
{
|
||||||
|
AutoLocker<Worker> workerLocker(GetWorker());
|
||||||
|
SimpleJobKey jobKey(node, JOB_TYPE_RESOLVE_VALUE_NODE_VALUE);
|
||||||
|
|
||||||
|
status_t error = B_OK;
|
||||||
|
if (GetWorker()->GetJob(jobKey) == NULL) {
|
||||||
|
workerLocker.Unlock();
|
||||||
|
|
||||||
|
// schedule the job
|
||||||
|
error = GetWorker()->ScheduleJob(
|
||||||
|
new(std::nothrow) ResolveValueNodeValueJob(fDebuggerInterface,
|
||||||
|
fArchitecture, fThread->GetCpuState(), fTypeInformation,
|
||||||
|
fManager->GetContainer(), node));
|
||||||
|
if (error != B_OK) {
|
||||||
|
// scheduling failed -- set the value to invalid
|
||||||
|
node->SetLocationAndValue(NULL, NULL, error);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for the job to finish
|
||||||
|
workerLocker.Unlock();
|
||||||
|
|
||||||
|
|
||||||
|
switch (WaitFor(jobKey)) {
|
||||||
|
case JOB_DEPENDENCY_SUCCEEDED:
|
||||||
|
case JOB_DEPENDENCY_NOT_FOUND:
|
||||||
|
case JOB_DEPENDENCY_ACTIVE:
|
||||||
|
error = B_OK;
|
||||||
|
break;
|
||||||
|
case JOB_DEPENDENCY_FAILED:
|
||||||
|
case JOB_DEPENDENCY_ABORTED:
|
||||||
|
default:
|
||||||
|
error = B_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ class ValueLocation;
|
|||||||
class ValueNode;
|
class ValueNode;
|
||||||
class ValueNodeChild;
|
class ValueNodeChild;
|
||||||
class ValueNodeContainer;
|
class ValueNodeContainer;
|
||||||
|
class ValueNodeManager;
|
||||||
class Variable;
|
class Variable;
|
||||||
|
|
||||||
|
|
||||||
@@ -233,22 +234,32 @@ private:
|
|||||||
class ExpressionEvaluationJob : public Job {
|
class ExpressionEvaluationJob : public Job {
|
||||||
public:
|
public:
|
||||||
ExpressionEvaluationJob(Team* team,
|
ExpressionEvaluationJob(Team* team,
|
||||||
|
DebuggerInterface* debuggerInterface,
|
||||||
SourceLanguage* language,
|
SourceLanguage* language,
|
||||||
const char* expression,
|
const char* expression,
|
||||||
type_code resultType,
|
type_code resultType,
|
||||||
StackFrame* frame);
|
StackFrame* frame,
|
||||||
|
Thread* thread);
|
||||||
virtual ~ExpressionEvaluationJob();
|
virtual ~ExpressionEvaluationJob();
|
||||||
|
|
||||||
virtual const JobKey& Key() const;
|
virtual const JobKey& Key() const;
|
||||||
virtual status_t Do();
|
virtual status_t Do();
|
||||||
|
|
||||||
|
private:
|
||||||
|
status_t ResolveNodeValue(ValueNode* node);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SimpleJobKey fKey;
|
SimpleJobKey fKey;
|
||||||
Team* fTeam;
|
Team* fTeam;
|
||||||
|
DebuggerInterface* fDebuggerInterface;
|
||||||
|
Architecture* fArchitecture;
|
||||||
|
TeamTypeInformation* fTypeInformation;
|
||||||
SourceLanguage* fLanguage;
|
SourceLanguage* fLanguage;
|
||||||
BString fExpression;
|
BString fExpression;
|
||||||
type_code fResultType;
|
type_code fResultType;
|
||||||
StackFrame* fFrame;
|
StackFrame* fFrame;
|
||||||
|
Thread* fThread;
|
||||||
|
ValueNodeManager* fManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -167,14 +167,15 @@ CLanguageFamily::ParseTypeExpression(const BString& expression,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
CLanguageFamily::EvaluateExpression(const BString& expression,
|
CLanguageFamily::EvaluateExpression(const BString& expression, type_code type,
|
||||||
type_code type, Value*& _output)
|
ValueNodeManager* manager, Value*& _output, ValueNode*& _neededNode)
|
||||||
{
|
{
|
||||||
_output = NULL;
|
_output = NULL;
|
||||||
|
_neededNode = NULL;
|
||||||
CLanguageExpressionEvaluator evaluator;
|
CLanguageExpressionEvaluator evaluator;
|
||||||
Number result;
|
Number result;
|
||||||
try {
|
try {
|
||||||
result = evaluator.Evaluate(expression, type);
|
result = evaluator.Evaluate(expression, type, manager);
|
||||||
BVariant resultValue = result.GetValue();
|
BVariant resultValue = result.GetValue();
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case B_INT8_TYPE:
|
case B_INT8_TYPE:
|
||||||
@@ -207,6 +208,8 @@ CLanguageFamily::EvaluateExpression(const BString& expression,
|
|||||||
ex.position, ex.message.String());
|
ex.position, ex.message.String());
|
||||||
_output = new(std::nothrow) StringValue(stringValue);
|
_output = new(std::nothrow) StringValue(stringValue);
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
|
} catch (ValueNeededException ex) {
|
||||||
|
_neededNode = ex.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ public:
|
|||||||
Type*& _resultType) const;
|
Type*& _resultType) const;
|
||||||
|
|
||||||
virtual status_t EvaluateExpression(const BString& expression,
|
virtual status_t EvaluateExpression(const BString& expression,
|
||||||
type_code type, Value*& _output);
|
type_code type, ValueNodeManager* manager,
|
||||||
|
Value*& _output, ValueNode*& _neededNode);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool IsModifierValid(char modifier) const = 0;
|
virtual bool IsModifierValid(char modifier) const = 0;
|
||||||
|
|||||||
@@ -30,7 +30,8 @@ SourceLanguage::ParseTypeExpression(const BString& expression,
|
|||||||
|
|
||||||
status_t
|
status_t
|
||||||
SourceLanguage::EvaluateExpression(const BString& expression,
|
SourceLanguage::EvaluateExpression(const BString& expression,
|
||||||
type_code type, Value*& _resultValue)
|
type_code type, ValueNodeManager* manager, Value*& _resultValue,
|
||||||
|
ValueNode*& _neededNode)
|
||||||
{
|
{
|
||||||
return B_NOT_SUPPORTED;
|
return B_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ class SyntaxHighlighter;
|
|||||||
class TeamTypeInformation;
|
class TeamTypeInformation;
|
||||||
class Type;
|
class Type;
|
||||||
class Value;
|
class Value;
|
||||||
|
class ValueNode;
|
||||||
|
class ValueNodeManager;
|
||||||
|
|
||||||
|
|
||||||
class SourceLanguage : public BReferenceable {
|
class SourceLanguage : public BReferenceable {
|
||||||
@@ -32,7 +34,8 @@ public:
|
|||||||
Type*& _resultType) const;
|
Type*& _resultType) const;
|
||||||
|
|
||||||
virtual status_t EvaluateExpression(const BString& expression,
|
virtual status_t EvaluateExpression(const BString& expression,
|
||||||
type_code type, Value*& _output);
|
type_code type, ValueNodeManager* manager,
|
||||||
|
Value*& _output, ValueNode*& _neededNode);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+64
-27
@@ -11,13 +11,21 @@
|
|||||||
|
|
||||||
#include "CLanguageExpressionEvaluator.h"
|
#include "CLanguageExpressionEvaluator.h"
|
||||||
|
|
||||||
#include "Number.h"
|
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
|
|
||||||
|
#include "AutoLocker.h"
|
||||||
|
|
||||||
|
#include "Number.h"
|
||||||
|
#include "StackFrame.h"
|
||||||
|
#include "Thread.h"
|
||||||
|
#include "Value.h"
|
||||||
|
#include "ValueNode.h"
|
||||||
|
#include "ValueNodeManager.h"
|
||||||
|
#include "Variable.h"
|
||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
TOKEN_NONE = 0,
|
TOKEN_NONE = 0,
|
||||||
@@ -299,7 +307,7 @@ class CLanguageExpressionEvaluator::Tokenizer {
|
|||||||
fCurrentToken = Token(begin, length, _CurrentPos() - length,
|
fCurrentToken = Token(begin, length, _CurrentPos() - length,
|
||||||
TOKEN_CONSTANT);
|
TOKEN_CONSTANT);
|
||||||
fCurrentToken.value.SetTo(fType, temp.String());
|
fCurrentToken.value.SetTo(fType, temp.String());
|
||||||
} else if (isalpha(*fCurrentChar) && *fCurrentChar != 'x') {
|
} else if (isalpha(*fCurrentChar)) {
|
||||||
const char* begin = fCurrentChar;
|
const char* begin = fCurrentChar;
|
||||||
while (*fCurrentChar != 0 && (isalpha(*fCurrentChar)
|
while (*fCurrentChar != 0 && (isalpha(*fCurrentChar)
|
||||||
|| isdigit(*fCurrentChar))) {
|
|| isdigit(*fCurrentChar))) {
|
||||||
@@ -308,10 +316,6 @@ class CLanguageExpressionEvaluator::Tokenizer {
|
|||||||
int32 length = fCurrentChar - begin;
|
int32 length = fCurrentChar - begin;
|
||||||
fCurrentToken = Token(begin, length, _CurrentPos() - length,
|
fCurrentToken = Token(begin, length, _CurrentPos() - length,
|
||||||
TOKEN_IDENTIFIER);
|
TOKEN_IDENTIFIER);
|
||||||
} else if (strncmp(fCurrentChar, "π", 2) == 0) {
|
|
||||||
fCurrentToken = Token(fCurrentChar, 2, _CurrentPos() - 1,
|
|
||||||
TOKEN_IDENTIFIER);
|
|
||||||
fCurrentChar += 2;
|
|
||||||
} else {
|
} else {
|
||||||
if (!_ParseOperator()) {
|
if (!_ParseOperator()) {
|
||||||
int32 type = TOKEN_NONE;
|
int32 type = TOKEN_NONE;
|
||||||
@@ -517,7 +521,8 @@ class CLanguageExpressionEvaluator::Tokenizer {
|
|||||||
CLanguageExpressionEvaluator::CLanguageExpressionEvaluator()
|
CLanguageExpressionEvaluator::CLanguageExpressionEvaluator()
|
||||||
:
|
:
|
||||||
fTokenizer(new Tokenizer()),
|
fTokenizer(new Tokenizer()),
|
||||||
fCurrentType(B_INT64_TYPE)
|
fCurrentType(B_INT64_TYPE),
|
||||||
|
fNodeManager(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,10 +535,10 @@ CLanguageExpressionEvaluator::~CLanguageExpressionEvaluator()
|
|||||||
|
|
||||||
Number
|
Number
|
||||||
CLanguageExpressionEvaluator::Evaluate(const char* expressionString,
|
CLanguageExpressionEvaluator::Evaluate(const char* expressionString,
|
||||||
type_code type)
|
type_code type, ValueNodeManager* manager)
|
||||||
{
|
{
|
||||||
fCurrentType = type;
|
fCurrentType = type;
|
||||||
|
fNodeManager = manager;
|
||||||
fTokenizer->SetType(type);
|
fTokenizer->SetType(type);
|
||||||
fTokenizer->SetTo(expressionString);
|
fTokenizer->SetTo(expressionString);
|
||||||
|
|
||||||
@@ -745,6 +750,7 @@ CLanguageExpressionEvaluator::_ParseUnary()
|
|||||||
return Number((int32)(_ParseUnary() == Number(BVariant(0L))));
|
return Number((int32)(_ParseUnary() == Number(BVariant(0L))));
|
||||||
|
|
||||||
case TOKEN_IDENTIFIER:
|
case TOKEN_IDENTIFIER:
|
||||||
|
fTokenizer->RewindToken();
|
||||||
return _ParseIdentifier();
|
return _ParseIdentifier();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -756,32 +762,63 @@ CLanguageExpressionEvaluator::_ParseUnary()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct Function {
|
|
||||||
const char* name;
|
|
||||||
int argumentCount;
|
|
||||||
void* function;
|
|
||||||
Number value;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
Number
|
Number
|
||||||
CLanguageExpressionEvaluator::_ParseIdentifier()
|
CLanguageExpressionEvaluator::_ParseIdentifier()
|
||||||
{
|
{
|
||||||
throw ParseException("Identifiers not implemented", 0);
|
Token token = fTokenizer->NextToken();
|
||||||
|
Number value;
|
||||||
|
|
||||||
return Number();
|
if (fNodeManager == NULL) {
|
||||||
|
throw ParseException("Identifiers not resolvable without manager.",
|
||||||
|
token.position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const BString& identifierName = token.string;
|
||||||
|
|
||||||
void
|
ValueNodeContainer* container = fNodeManager->GetContainer();
|
||||||
CLanguageExpressionEvaluator::_InitArguments(Number values[], int32 argumentCount)
|
AutoLocker<ValueNodeContainer> containerLocker(container);
|
||||||
{
|
|
||||||
_EatToken(TOKEN_OPENING_BRACKET);
|
|
||||||
|
|
||||||
for (int32 i = 0; i < argumentCount; i++)
|
ValueNodeChild* child = NULL;
|
||||||
values[i] = _ParseBinary();
|
for (int32 i = 0; i < container->CountChildren(); i++) {
|
||||||
|
ValueNodeChild* current = container->ChildAt(i);
|
||||||
|
if (current->Name() == identifierName) {
|
||||||
|
child = current;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_EatToken(TOKEN_CLOSING_BRACKET);
|
BString errorMessage;
|
||||||
|
if (child == NULL) {
|
||||||
|
errorMessage.SetToFormat("Unable to resolve variable name: '%s'",
|
||||||
|
identifierName.String());
|
||||||
|
throw ParseException(errorMessage, token.position);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t state = child->LocationResolutionState();
|
||||||
|
if (state != B_OK) {
|
||||||
|
errorMessage.SetToFormat("Unable to resolve variable value for '%s': "
|
||||||
|
"%s", identifierName.String(),
|
||||||
|
strerror(state));
|
||||||
|
throw ParseException(errorMessage, token.position);
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueNode* node = child->Node();
|
||||||
|
state = node->LocationAndValueResolutionState();
|
||||||
|
if (state == VALUE_NODE_UNRESOLVED) {
|
||||||
|
throw ValueNeededException(node);
|
||||||
|
} else if (state != B_OK) {
|
||||||
|
errorMessage.SetToFormat("Unable to resolve variable value for '%s': "
|
||||||
|
"%s", identifierName.String(),
|
||||||
|
strerror(state));
|
||||||
|
throw ParseException(errorMessage, token.position);
|
||||||
|
}
|
||||||
|
|
||||||
|
BVariant variant;
|
||||||
|
Value* nodeValue = node->GetValue();
|
||||||
|
nodeValue->ToVariant(variant);
|
||||||
|
value.SetTo(variant);
|
||||||
|
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+19
-4
@@ -15,6 +15,10 @@
|
|||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
|
|
||||||
|
class ValueNode;
|
||||||
|
class ValueNodeManager;
|
||||||
|
|
||||||
|
|
||||||
class ParseException {
|
class ParseException {
|
||||||
public:
|
public:
|
||||||
ParseException(const char* message, int32 position)
|
ParseException(const char* message, int32 position)
|
||||||
@@ -33,9 +37,21 @@ class ParseException {
|
|||||||
int32 position;
|
int32 position;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Function;
|
class ValueNeededException {
|
||||||
|
public:
|
||||||
|
ValueNeededException(ValueNode* node)
|
||||||
|
:
|
||||||
|
value(node)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueNode* value;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class Number;
|
class Number;
|
||||||
|
|
||||||
|
|
||||||
class CLanguageExpressionEvaluator {
|
class CLanguageExpressionEvaluator {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -43,7 +59,7 @@ class CLanguageExpressionEvaluator {
|
|||||||
~CLanguageExpressionEvaluator();
|
~CLanguageExpressionEvaluator();
|
||||||
|
|
||||||
Number Evaluate(const char* expressionString,
|
Number Evaluate(const char* expressionString,
|
||||||
type_code type);
|
type_code type, ValueNodeManager* manager);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Token;
|
struct Token;
|
||||||
@@ -56,14 +72,13 @@ class CLanguageExpressionEvaluator {
|
|||||||
Number _ParsePower();
|
Number _ParsePower();
|
||||||
Number _ParseUnary();
|
Number _ParseUnary();
|
||||||
Number _ParseIdentifier();
|
Number _ParseIdentifier();
|
||||||
void _InitArguments(Number values[],
|
|
||||||
int32 argumentCount);
|
|
||||||
Number _ParseAtom();
|
Number _ParseAtom();
|
||||||
|
|
||||||
void _EatToken(int32 type);
|
void _EatToken(int32 type);
|
||||||
|
|
||||||
Tokenizer* fTokenizer;
|
Tokenizer* fTokenizer;
|
||||||
type_code fCurrentType;
|
type_code fCurrentType;
|
||||||
|
ValueNodeManager* fNodeManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // C_LANGUAGE_EXPRESSION_EVALUATOR_H
|
#endif // C_LANGUAGE_EXPRESSION_EVALUATOR_H
|
||||||
|
|||||||
@@ -141,7 +141,8 @@ public:
|
|||||||
SourceLanguage* language,
|
SourceLanguage* language,
|
||||||
const char* expression,
|
const char* expression,
|
||||||
type_code resultType,
|
type_code resultType,
|
||||||
StackFrame* frame = NULL) = 0;
|
StackFrame* frame = NULL,
|
||||||
|
Thread* thread = NULL) = 0;
|
||||||
|
|
||||||
virtual void DebugReportRequested(entry_ref* path) = 0;
|
virtual void DebugReportRequested(entry_ref* path) = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
#include "MessageCodes.h"
|
#include "MessageCodes.h"
|
||||||
#include "SourceLanguage.h"
|
#include "SourceLanguage.h"
|
||||||
|
#include "StackFrame.h"
|
||||||
|
#include "Thread.h"
|
||||||
#include "UserInterface.h"
|
#include "UserInterface.h"
|
||||||
#include "Value.h"
|
#include "Value.h"
|
||||||
|
|
||||||
@@ -26,8 +28,8 @@ enum {
|
|||||||
|
|
||||||
|
|
||||||
ExpressionEvaluationWindow::ExpressionEvaluationWindow(
|
ExpressionEvaluationWindow::ExpressionEvaluationWindow(
|
||||||
::Team* team, SourceLanguage* language, UserInterfaceListener* listener,
|
::Team* team, SourceLanguage* language, StackFrame* frame,
|
||||||
BHandler* target)
|
::Thread* thread, UserInterfaceListener* listener, BHandler* target)
|
||||||
:
|
:
|
||||||
BWindow(BRect(), "Evaluate Expression", B_FLOATING_WINDOW,
|
BWindow(BRect(), "Evaluate Expression", B_FLOATING_WINDOW,
|
||||||
B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE),
|
B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE),
|
||||||
@@ -37,11 +39,19 @@ ExpressionEvaluationWindow::ExpressionEvaluationWindow(
|
|||||||
fExpressionOutput(NULL),
|
fExpressionOutput(NULL),
|
||||||
fEvaluateButton(NULL),
|
fEvaluateButton(NULL),
|
||||||
fListener(listener),
|
fListener(listener),
|
||||||
|
fStackFrame(frame),
|
||||||
|
fThread(thread),
|
||||||
fCloseTarget(target),
|
fCloseTarget(target),
|
||||||
fCurrentEvaluationType(B_INT64_TYPE)
|
fCurrentEvaluationType(B_INT64_TYPE)
|
||||||
{
|
{
|
||||||
fLanguage->AcquireReference();
|
fLanguage->AcquireReference();
|
||||||
|
|
||||||
|
if (fStackFrame != NULL)
|
||||||
|
fStackFrame->AcquireReference();
|
||||||
|
|
||||||
|
if (fThread != NULL)
|
||||||
|
fThread->AcquireReference();
|
||||||
|
|
||||||
AutoLocker< ::Team> teamLocker(fTeam);
|
AutoLocker< ::Team> teamLocker(fTeam);
|
||||||
fTeam->AddListener(this);
|
fTeam->AddListener(this);
|
||||||
}
|
}
|
||||||
@@ -51,6 +61,12 @@ ExpressionEvaluationWindow::~ExpressionEvaluationWindow()
|
|||||||
{
|
{
|
||||||
fLanguage->ReleaseReference();
|
fLanguage->ReleaseReference();
|
||||||
|
|
||||||
|
if (fStackFrame != NULL)
|
||||||
|
fStackFrame->ReleaseReference();
|
||||||
|
|
||||||
|
if (fThread != NULL)
|
||||||
|
fThread->ReleaseReference();
|
||||||
|
|
||||||
AutoLocker< ::Team> teamLocker(fTeam);
|
AutoLocker< ::Team> teamLocker(fTeam);
|
||||||
fTeam->RemoveListener(this);
|
fTeam->RemoveListener(this);
|
||||||
}
|
}
|
||||||
@@ -58,10 +74,11 @@ ExpressionEvaluationWindow::~ExpressionEvaluationWindow()
|
|||||||
|
|
||||||
ExpressionEvaluationWindow*
|
ExpressionEvaluationWindow*
|
||||||
ExpressionEvaluationWindow::Create(::Team* team, SourceLanguage* language,
|
ExpressionEvaluationWindow::Create(::Team* team, SourceLanguage* language,
|
||||||
UserInterfaceListener* listener, BHandler* target)
|
StackFrame* frame, ::Thread* thread, UserInterfaceListener* listener,
|
||||||
|
BHandler* target)
|
||||||
{
|
{
|
||||||
ExpressionEvaluationWindow* self = new ExpressionEvaluationWindow(team,
|
ExpressionEvaluationWindow* self = new ExpressionEvaluationWindow(team,
|
||||||
language, listener, target);
|
language, frame, thread, listener, target);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
self->_Init();
|
self->_Init();
|
||||||
@@ -216,7 +233,8 @@ ExpressionEvaluationWindow::MessageReceived(BMessage* message)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
fListener->ExpressionEvaluationRequested(fLanguage,
|
fListener->ExpressionEvaluationRequested(fLanguage,
|
||||||
fExpressionInput->Text(), fCurrentEvaluationType);
|
fExpressionInput->Text(), fCurrentEvaluationType, fStackFrame,
|
||||||
|
fThread);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,9 @@ class BButton;
|
|||||||
class BStringView;
|
class BStringView;
|
||||||
class BTextControl;
|
class BTextControl;
|
||||||
class Team;
|
class Team;
|
||||||
|
class Thread;
|
||||||
class SourceLanguage;
|
class SourceLanguage;
|
||||||
|
class StackFrame;
|
||||||
class UserInterfaceListener;
|
class UserInterfaceListener;
|
||||||
|
|
||||||
|
|
||||||
@@ -26,6 +28,8 @@ public:
|
|||||||
ExpressionEvaluationWindow(
|
ExpressionEvaluationWindow(
|
||||||
::Team* team,
|
::Team* team,
|
||||||
SourceLanguage* language,
|
SourceLanguage* language,
|
||||||
|
StackFrame* frame,
|
||||||
|
::Thread* thread,
|
||||||
UserInterfaceListener* listener,
|
UserInterfaceListener* listener,
|
||||||
BHandler* target);
|
BHandler* target);
|
||||||
|
|
||||||
@@ -34,6 +38,8 @@ public:
|
|||||||
static ExpressionEvaluationWindow* Create(
|
static ExpressionEvaluationWindow* Create(
|
||||||
::Team* team,
|
::Team* team,
|
||||||
SourceLanguage* language,
|
SourceLanguage* language,
|
||||||
|
StackFrame* frame,
|
||||||
|
::Thread* thread,
|
||||||
UserInterfaceListener* listener,
|
UserInterfaceListener* listener,
|
||||||
BHandler* target);
|
BHandler* target);
|
||||||
// throws
|
// throws
|
||||||
@@ -60,6 +66,8 @@ private:
|
|||||||
BStringView* fExpressionOutput;
|
BStringView* fExpressionOutput;
|
||||||
BButton* fEvaluateButton;
|
BButton* fEvaluateButton;
|
||||||
UserInterfaceListener* fListener;
|
UserInterfaceListener* fListener;
|
||||||
|
StackFrame* fStackFrame;
|
||||||
|
::Thread* fThread;
|
||||||
BHandler* fCloseTarget;
|
BHandler* fCloseTarget;
|
||||||
type_code fCurrentEvaluationType;
|
type_code fCurrentEvaluationType;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -356,7 +356,8 @@ TeamWindow::MessageReceived(BMessage* message)
|
|||||||
BReference<SourceLanguage> languageReference(language,
|
BReference<SourceLanguage> languageReference(language,
|
||||||
true);
|
true);
|
||||||
fExpressionWindow = ExpressionEvaluationWindow::Create(
|
fExpressionWindow = ExpressionEvaluationWindow::Create(
|
||||||
fTeam, language, fListener, this);
|
fTeam, language, fActiveStackFrame, fActiveThread,
|
||||||
|
fListener, this);
|
||||||
if (fExpressionWindow != NULL)
|
if (fExpressionWindow != NULL)
|
||||||
fExpressionWindow->Show();
|
fExpressionWindow->Show();
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
|
|||||||
Reference in New Issue
Block a user