Add naive expression dumping for menus for debugging purposes

This commit is contained in:
Jan 2024-01-06 19:39:07 +01:00
parent 6eca361517
commit c4150279d0
No known key found for this signature in database
GPG Key ID: 44B581F78FF5C57C
4 changed files with 191 additions and 7 deletions

View File

@ -9,7 +9,16 @@
using namespace IW4;
size_t MenuDumper::FindStatementClosingParenthesis(const Statement_s* statement, size_t openingParenthesisPosition)
// Uncomment this macro to skip interpretative expression dumping
// #define DUMP_NAIVE
#ifdef DUMP_NAIVE
#define DUMP_FUNC WriteStatementNaive
#else
#define DUMP_FUNC WriteStatementSkipInitialUnnecessaryParenthesis
#endif
size_t MenuDumper::FindStatementClosingParenthesis(const Statement_s* statement, const size_t openingParenthesisPosition)
{
assert(statement->numEntries >= 0);
assert(openingParenthesisPosition < static_cast<size_t>(statement->numEntries));
@ -206,7 +215,7 @@ void MenuDumper::WriteStatementOperand(const Statement_s* statement, size_t& cur
spaceNext = true;
}
void MenuDumper::WriteStatementEntryRange(const Statement_s* statement, size_t startOffset, size_t endOffset) const
void MenuDumper::WriteStatementEntryRange(const Statement_s* statement, const size_t startOffset, const size_t endOffset) const
{
assert(startOffset <= endOffset);
assert(endOffset <= static_cast<size_t>(statement->numEntries));
@ -260,6 +269,91 @@ void MenuDumper::WriteStatementSkipInitialUnnecessaryParenthesis(const Statement
}
}
void MenuDumper::WriteStatementNaive(const Statement_s* statement) const
{
const auto entryCount = static_cast<unsigned>(statement->numEntries);
const auto missingClosingParenthesis = statement->numEntries > 0 && statement->entries[0].type == EET_OPERATOR
&& statement->entries[0].data.op == OP_LEFTPAREN
&& FindStatementClosingParenthesis(statement, 0) >= static_cast<size_t>(statement->numEntries);
for (auto i = 0u; i < entryCount; i++)
{
const auto& entry = statement->entries[i];
if (entry.type == EET_OPERAND)
{
size_t pos = i;
bool discard = false;
WriteStatementOperand(statement, pos, discard);
}
else if (entry.data.op >= EXP_FUNC_STATIC_DVAR_INT && entry.data.op <= EXP_FUNC_STATIC_DVAR_STRING)
{
switch (entry.data.op)
{
case EXP_FUNC_STATIC_DVAR_INT:
m_stream << "dvarint";
break;
case EXP_FUNC_STATIC_DVAR_BOOL:
m_stream << "dvarbool";
break;
case EXP_FUNC_STATIC_DVAR_FLOAT:
m_stream << "dvarfloat";
break;
case EXP_FUNC_STATIC_DVAR_STRING:
m_stream << "dvarstring";
break;
default:
break;
}
// Functions do not have opening parenthesis in the entries. We can just pretend they do though
const auto closingParenPos = FindStatementClosingParenthesis(statement, i);
m_stream << "(";
if (closingParenPos - i + 1 >= 1)
{
const auto& staticDvarEntry = statement->entries[i + 1];
if (staticDvarEntry.type == EET_OPERAND && staticDvarEntry.data.operand.dataType == VAL_INT)
{
if (statement->supportingData && statement->supportingData->staticDvarList.staticDvars && staticDvarEntry.data.operand.internals.intVal >= 0
&& staticDvarEntry.data.operand.internals.intVal < statement->supportingData->staticDvarList.numStaticDvars)
{
const auto* staticDvar = statement->supportingData->staticDvarList.staticDvars[staticDvarEntry.data.operand.internals.intVal];
if (staticDvar && staticDvar->dvarName)
m_stream << staticDvar->dvarName;
}
else
{
m_stream << "#INVALID_DVAR_INDEX";
}
}
else
{
m_stream << "#INVALID_DVAR_OPERAND";
}
}
m_stream << ")";
i = closingParenPos;
}
else
{
assert(entry.data.op >= 0 && static_cast<unsigned>(entry.data.op) < std::extent_v<decltype(g_expFunctionNames)>);
if (entry.data.op >= 0 && static_cast<unsigned>(entry.data.op) < std::extent_v<decltype(g_expFunctionNames)>)
m_stream << g_expFunctionNames[entry.data.op];
if (entry.data.op >= OP_COUNT)
m_stream << "(";
}
}
if (missingClosingParenthesis)
m_stream << ")";
}
void MenuDumper::WriteStatementProperty(const std::string& propertyKey, const Statement_s* statementValue, bool isBooleanStatement) const
{
if (statementValue == nullptr || statementValue->numEntries < 0)
@ -271,12 +365,12 @@ void MenuDumper::WriteStatementProperty(const std::string& propertyKey, const St
if (isBooleanStatement)
{
m_stream << "when(";
WriteStatementSkipInitialUnnecessaryParenthesis(statementValue);
DUMP_FUNC(statementValue);
m_stream << ");\n";
}
else
{
WriteStatementSkipInitialUnnecessaryParenthesis(statementValue);
DUMP_FUNC(statementValue);
m_stream << ";\n";
}
}

View File

@ -11,6 +11,8 @@ namespace IW4
{
static size_t FindStatementClosingParenthesis(const Statement_s* statement, size_t openingParenthesisPosition);
void WriteStatementNaive(const Statement_s* statement) const;
void WriteStatementOperator(const Statement_s* statement, size_t& currentPos, bool& spaceNext) const;
void WriteStatementOperandFunction(const Statement_s* statement, size_t currentPos) const;
void WriteStatementOperand(const Statement_s* statement, size_t& currentPos, bool& spaceNext) const;

View File

@ -9,6 +9,15 @@
using namespace IW5;
// Uncomment this macro to skip interpretative expression dumping
// #define DUMP_NAIVE
#ifdef DUMP_NAIVE
#define DUMP_FUNC WriteStatementNaive
#else
#define DUMP_FUNC WriteStatementSkipInitialUnnecessaryParenthesis
#endif
size_t MenuDumper::FindStatementClosingParenthesis(const Statement_s* statement, size_t openingParenthesisPosition)
{
assert(statement->numEntries >= 0);
@ -23,7 +32,7 @@ size_t MenuDumper::FindStatementClosingParenthesis(const Statement_s* statement,
{
const auto& expEntry = statement->entries[currentSearchPosition];
if (expEntry.type != EET_OPERATOR)
continue;
continue;
// Any function means a "left out" left paren
if (expEntry.data.op == OP_LEFTPAREN || expEntry.data.op >= OP_COUNT)
@ -228,6 +237,83 @@ void MenuDumper::WriteStatementEntryRange(const Statement_s* statement, size_t s
}
}
void MenuDumper::WriteStatementNaive(const Statement_s* statement) const
{
const auto entryCount = static_cast<unsigned>(statement->numEntries);
for (auto i = 0u; i < entryCount; i++)
{
const auto& entry = statement->entries[i];
if (entry.type == EET_OPERAND)
{
size_t pos = i;
bool discard = false;
WriteStatementOperand(statement, pos, discard);
}
else if (entry.data.op >= EXP_FUNC_STATIC_DVAR_INT && entry.data.op <= EXP_FUNC_STATIC_DVAR_STRING)
{
switch (entry.data.op)
{
case EXP_FUNC_STATIC_DVAR_INT:
m_stream << "dvarint";
break;
case EXP_FUNC_STATIC_DVAR_BOOL:
m_stream << "dvarbool";
break;
case EXP_FUNC_STATIC_DVAR_FLOAT:
m_stream << "dvarfloat";
break;
case EXP_FUNC_STATIC_DVAR_STRING:
m_stream << "dvarstring";
break;
default:
break;
}
// Functions do not have opening parenthesis in the entries. We can just pretend they do though
const auto closingParenPos = FindStatementClosingParenthesis(statement, i);
m_stream << "(";
if (closingParenPos - i + 1 >= 1)
{
const auto& staticDvarEntry = statement->entries[i + 1];
if (staticDvarEntry.type == EET_OPERAND && staticDvarEntry.data.operand.dataType == VAL_INT)
{
if (statement->supportingData && statement->supportingData->staticDvarList.staticDvars && staticDvarEntry.data.operand.internals.intVal >= 0
&& staticDvarEntry.data.operand.internals.intVal < statement->supportingData->staticDvarList.numStaticDvars)
{
const auto* staticDvar = statement->supportingData->staticDvarList.staticDvars[staticDvarEntry.data.operand.internals.intVal];
if (staticDvar && staticDvar->dvarName)
m_stream << staticDvar->dvarName;
}
else
{
m_stream << "#INVALID_DVAR_INDEX";
}
}
else
{
m_stream << "#INVALID_DVAR_OPERAND";
}
}
m_stream << ")";
i = closingParenPos;
}
else
{
assert(entry.data.op >= 0 && static_cast<unsigned>(entry.data.op) < std::extent_v<decltype(g_expFunctionNames)>);
if (entry.data.op >= 0 && static_cast<unsigned>(entry.data.op) < std::extent_v<decltype(g_expFunctionNames)>)
m_stream << g_expFunctionNames[entry.data.op];
if (entry.data.op >= OP_COUNT)
m_stream << "(";
}
}
}
void MenuDumper::WriteStatement(const Statement_s* statement) const
{
if (statement == nullptr || statement->numEntries < 0)
@ -271,12 +357,12 @@ void MenuDumper::WriteStatementProperty(const std::string& propertyKey, const St
if (isBooleanStatement)
{
m_stream << "when(";
WriteStatementSkipInitialUnnecessaryParenthesis(statementValue);
DUMP_FUNC(statementValue);
m_stream << ");\n";
}
else
{
WriteStatementSkipInitialUnnecessaryParenthesis(statementValue);
DUMP_FUNC(statementValue);
m_stream << ";\n";
}
}

View File

@ -11,6 +11,8 @@ namespace IW5
{
static size_t FindStatementClosingParenthesis(const Statement_s* statement, size_t openingParenthesisPosition);
void WriteStatementNaive(const Statement_s* statement) const;
void WriteStatementOperator(const Statement_s* statement, size_t& currentPos, bool& spaceNext) const;
void WriteStatementOperandFunction(const Statement_s* statement, size_t currentPos) const;
void WriteStatementOperand(const Statement_s* statement, size_t& currentPos, bool& spaceNext) const;